diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..2b04565 --- /dev/null +++ b/.pydevproject @@ -0,0 +1,5 @@ + + + Default + python interpreter + diff --git a/CHANGELOG.md b/CHANGELOG.md index 556dd40..9c50060 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ + + + # CHANGELOG ## 0.1.0-pre.001 @@ -19,5 +22,10 @@ - Portage des contrats complets de `kb_decoder_api` dans `kb-lib::decoder::api`. - Portage des contrats complets de `kb_materializer_api` dans `kb-lib::materializer::api`. - Portage des contrats complets de `kb_execution_api` dans `kb-lib::executor::api`. -- Ajout du contrat neutre `CoreInstructionReplayInput` dans `kb-lib` pour éviter une dépendance cyclique avec `kb-store`. +- Ajout du contrat neutre `MdCoreInstructionReplayInput` dans `kb-lib` pour éviter une dépendance cyclique avec `kb-store`. - `kb-lib/src/lib.rs` reste une façade de modules et de réexports. + +## 0.1.0-pre.010 + +- Portage des matérialisateurs natifs lifecycle, administration, compliance et staking. +- Conservation de leurs 50 tests historiques et ajout du premier test aval de matérialisation. diff --git a/README.md b/README.md index 12cb6da..17067a1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ - + # Khadhroony Bot3 @@ -63,9 +63,19 @@ cargo clippy --workspace --all-targets `0.1.0-pre.010` porte les quatre matérialisateurs Solana natifs dans `kb-lib` : -- `LifecycleMaterializer` pour les comptes System, nonces, ALT, loaders, Feature Gate, contextes ZK et rapports Slashing ; -- `AdminMaterializer` pour les assignations, configurations et autorités, avec ses projections stateful Token‑2022 et registre ElGamal ; -- `ComplianceAuditMaterializer` pour les écritures et copies bornées de bytecode ; -- `StakingMaterializer` pour les transitions Stake et Vote commitées. +- `MtLifecycleMaterializer` pour les comptes System, nonces, ALT, loaders, Feature Gate, contextes ZK et rapports Slashing ; +- `MtAdminMaterializer` pour les assignations, configurations et autorités, avec ses projections stateful Token‑2022 et registre ElGamal ; +- `MtComplianceAuditMaterializer` pour les écritures et copies bornées de bytecode ; +- `MtStakingMaterializer` pour les transitions Stake et Vote commitées. -Les identités historiques des processors sont conservées pour la compatibilité des replays, tandis que les targets de tracing suivent désormais la hiérarchie `kb-lib.materializer.*`. Le contrat public `EventMaterializer`, ses modèles d’entrée et ses résultats restent réexportés à la racine de `kb-lib`, afin qu’un futur crate externe puisse fournir un matérialiseur sans dépendre d’une implémentation interne. +Les identités historiques des processors sont conservées pour la compatibilité des replays, tandis que les targets de tracing suivent désormais la hiérarchie `kb-lib.materializer.*`. Le contrat public `MtApiEventMaterializer`, ses modèles d’entrée et ses résultats restent réexportés à la racine de `kb-lib`, afin qu’un futur crate externe puisse fournir un matérialiseur sans dépendre d’une implémentation interne. + +`0.1.0-pre.011` termine le port des matérialisateurs réellement implémentés dans bot2 : + +- `MtTransactionAnnotationMaterializer` pour les Memo commitées ; +- `MtTokenAccountsMaterializer` pour les mutations SPL Token, le lifecycle ATA et les snapshots Token‑2022 ; +- `MtFeesMaterializer` pour les frais publics et confidentiels Token‑2022, sans prétendre déchiffrer les valeurs confidentielles ; +- `MtRiskMaterializer` pour les faits de risque SPL Token et ATA sans score arbitraire ; +- `MtMetadataMaterializer` pour les snapshots descriptifs Token‑2022 et Metaplex, sans fetch off-chain. + +Les modules de matérialisation sont privés. Tous les contrats, types concrets et helpers destinés aux consommateurs externes sont exposés exclusivement par `kb-lib/src/lib.rs`. Des tests aval distincts protègent les contrats d’extension `DcApiProtocolDecoder`, `MtApiEventMaterializer` et `ExApiInstructionExecutor`. diff --git a/ROADMAP.md b/ROADMAP.md index c3f5d49..56e5610 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,5 +1,5 @@ - + # ROADMAP — khadhroony-bot3 @@ -13,8 +13,8 @@ - [x] Porter exactement les contrats publics de `kb_decoder_api`. - [x] Porter exactement les contrats publics des APIs d’exécution et de matérialisation. - [x] Porter les modèles de `kb_model` vers `kb-lib`. -- [~] Porter les décodeurs Solana core, SPL et Metaplex. -- [~] Porter leurs matérialisateurs. +- [x] Porter les décodeurs Solana core, SPL et Metaplex déjà implémentés dans bot2. +- [x] Porter leurs matérialisateurs déjà implémentés dans bot2. - [ ] Porter leurs exécuteurs. - [x] Fusionner `kb_store_core` et `kb_store_pg` dans `kb-store`. - [ ] Adapter `kb-pipeline` aux nouveaux chemins publics. @@ -37,7 +37,7 @@ - [x] Remplacer le scaffold par une architecture intégrée contrats/adaptateurs. - [x] Porter les DTO, entités, traits et validations store-neutral. - [x] Porter l’adaptateur PostgreSQL, ses requêtes, diagnostics et initialisations idempotentes. -- [x] Conserver `CoreInstructionReplayInput` dans `kb-lib` et le réexporter depuis `kb-store`. +- [x] Conserver `MdCoreInstructionReplayInput` dans `kb-lib` et le réexporter depuis `kb-store`. - [x] Supprimer la dépendance directe de `kb-store` vers `kb-config`. - [x] Adapter les règles bot2 devenues incompatibles avec l’architecture bot3. - [x] Valider `cargo check`, les 84 tests et Clippy pour `kb-store`, puis `cargo check --workspace`. @@ -90,7 +90,7 @@ ### 0.1.0-pre.008 — Décodeurs Token‑2022 et registre ElGamal dans `kb-lib` -- [x] Remplacer les scaffolds `token_2022` et `elgamal_registry` par les décodeurs exacts validés de bot2. +- [x] Remplacer les scaffolds `token2022` et `elgamal_registry` par les décodeurs exacts validés de bot2. - [x] Conserver les 48 enveloppes Token‑2022, les sous-instructions d’extensions identifiables et les interfaces Metadata/Group incorporées. - [x] Porter le parseur borné des états Mint, Account et Multisig avec leurs entrées TLV ordonnées. - [x] Maintenir le registre ElGamal comme programme indépendant avec ses deux instructions et son état de compte exact de 64 octets. @@ -117,12 +117,25 @@ ### 0.1.0-pre.010 — Matérialisateurs Solana natifs dans `kb-lib` -- [x] Porter `LifecycleMaterializer`, `AdminMaterializer`, `ComplianceAuditMaterializer` et `StakingMaterializer` dans les modules consolidés de `kb-lib`. +- [x] Porter `MtLifecycleMaterializer`, `MtAdminMaterializer`, `MtComplianceAuditMaterializer` et `MtStakingMaterializer` dans les modules consolidés de `kb-lib`. - [x] Conserver leurs 50 tests de projections natives, de politique de transaction et d’idempotence. - [x] Réexporter les types concrets et les fonctions stateful publiques depuis la façade de `kb-lib`. -- [x] Ajouter un test d’intégration aval prouvant qu’un futur crate externe peut implémenter `EventMaterializer` avec la seule API publique. +- [x] Ajouter un test d’intégration aval prouvant qu’un futur crate externe peut implémenter `MtApiEventMaterializer` avec la seule API publique. - [x] Porter les targets vers `kb-lib.materializer.admin`, `kb-lib.materializer.compliance`, `kb-lib.materializer.lifecycle` et `kb-lib.materializer.staking`. - [x] Conserver les identités de processor historiques afin de préserver les clés de replay et d’idempotence existantes. - [x] Ajouter la règle d’ordre et d’absence de ligne vide interne dans les blocs de réexports publics. -- [ ] Valider les 371 tests attendus de `kb-lib`, Clippy et le workspace avec Cargo sur la machine de développement. -- [ ] Poursuivre avec les matérialisateurs Memo, SPL Token, ATA, Token‑2022, registre ElGamal et Metaplex. +- [x] Valider les 370 tests unitaires et le test d’intégration de `kb-lib`, Clippy et le workspace avec Cargo sur la machine de développement. +- [x] Poursuivre avec les matérialisateurs Memo, SPL Token, ATA, Token‑2022, registre ElGamal et Metaplex. + +### 0.1.0-pre.011 — Matérialisateurs SPL et Metaplex dans `kb-lib` + +- [x] Porter `MtTransactionAnnotationMaterializer`, `MtTokenAccountsMaterializer`, `MtFeesMaterializer`, `MtRiskMaterializer` et `MtMetadataMaterializer`. +- [x] Conserver leurs 45 tests historiques, en plus des 370 tests unitaires déjà validés. +- [x] Réexporter à la racine les cinq types concrets, les fonctions de snapshots Token‑2022/Metaplex et les types canoniques Metaplex nécessaires à leurs signatures publiques. +- [x] Rendre privée toute l’arborescence `kb-lib::materializer` et interdire mécaniquement tout nouveau `pub mod` dans cette frontière. +- [x] Étendre les tests aval aux trois contrats d’extension publics : `DcApiProtocolDecoder`, `MtApiEventMaterializer` et `ExApiInstructionExecutor`. +- [x] Étendre l’audit aux lignes vides internes des blocs homogènes `pub use` et `pub(crate) use`. +- [x] Porter les targets de risque, comptes Token et annotations vers `kb-lib.materializer.risk`, `kb-lib.materializer.token` et `kb-lib.materializer.transaction` dans les trois profils. +- [x] Maintenir le fetch HTTP/IPFS/Arweave hors de `kb-lib`, dans une future crate off-chain dédiée. +- [ ] Valider les 415 tests unitaires et les trois tests d’intégration de `kb-lib`, Clippy et le workspace avec Cargo sur la machine de développement. +- [ ] Poursuivre avec les exécuteurs déjà implémentés dans bot2. diff --git a/RULES.md b/RULES.md index 005e90b..91450e0 100644 --- a/RULES.md +++ b/RULES.md @@ -138,7 +138,7 @@ Aucun renommage massif de modules n'est autorisé sans étape de contrôle dédi - Une crate ou un composant de `kb-lib` est opérationnel lorsqu’il effectue des I/O, orchestre un pipeline, décode, matérialise, exécute, applique une politique runtime ou prend une décision mutable observable. - Toute crate opérationnelle ajoutée ou modifiée doit dépendre de `tracing` depuis le workspace et déclarer exactement un `pub(crate) const TRACING_TARGET` dans `src/constants.rs`. -- Hors `kb-lib`, la valeur canonique de `TRACING_TARGET` est le nom exact du package Cargo. +- Hors `kb-lib`, la valeur canonique de `DC_METADATA_MTM_TRACING_TARGET` est le nom exact du package Cargo. - Dans `kb-lib`, chaque composant opérationnel possède son propre `constants.rs` et un target hiérarchique stable fondé sur son identifiant de décodeur, matérialiseur ou exécuteur ; un target unique `kb-lib` ne doit pas effacer l'identité du composant. - Les targets historiques `khbot.*` et les targets de fenêtre sont interdits dans les nouvelles modifications. - Les macros `tracing` doivent utiliser `target: crate::TRACING_TARGET` et des champs structurés stables. La granularité interne passe par `action`, `stage`, `window`, `campaign_id`, `signature`, `instruction_path`, `program_id`, `processor_name`, `processor_version`, `status` et `error_code`. @@ -152,14 +152,14 @@ Aucun renommage massif de modules n'est autorisé sans étape de contrôle dédi - Chaque profil doit router les événements vers les sorties globales `debug.log`, `info.log`, `error.jsonl` et `app.log`, puis vers `debug.log`, `info.log` et `error.jsonl` dans un répertoire propre à chaque crate utilisant `tracing`. - L’ajout ou la suppression de `tracing.workspace = true` dans une crate impose la mise à jour simultanée de la matrice de routes, de ses tests et de `docs/TRACING_CONTRACT.md`. - Le contrat détaillé est défini dans `docs/TRACING_CONTRACT.md`. -- L’audit mécanique spécifique au projet est exécuté par `python3 scripts/audit_khadhroony_workspace_rules.py`. Il couvre notamment `TRACING_TARGET` et l’usage obligatoire de `solana_pubkey::Pubkey` à la place de `solana_address::Address`. +- L’audit mécanique spécifique au projet est exécuté par `python3 scripts/audit_khadhroony_workspace_rules.py`. Il couvre notamment `DC_METADATA_MTM_TRACING_TARGET` et l’usage obligatoire de `solana_pubkey::Pubkey` à la place de `solana_address::Address`. ## Règles de réutilisation des interfaces Solana et SPL - Les dépendances déclarées dans `[workspace.dependencies]` forment un catalogue de versions et de features autorisées ; elles ne doivent être ajoutées à une crate consommatrice que lorsqu’un type, un encodeur, un décodeur ou un identifiant officiel est réellement utilisé. - Dans un `Cargo.toml`, placer dans `[dependencies]` toute crate référencée par le code de bibliothèque compilé en production. Réserver `[dev-dependencies]` aux références contenues exclusivement dans `#[cfg(test)]`, les tests d’intégration, benches ou exemples. Une dépendance de test vers un décodeur ou matérialiseur concret est légitime lorsqu’elle sert uniquement à éprouver une orchestration générique fondée sur les traits API ; elle ne prouve pas qu’une capacité de production manque. Toute promotion de `dev-dependencies` vers `dependencies` doit être motivée par un appel runtime réel, et toute dépendance runtime inutilisée doit être supprimée. -- Les registres de composition runtime des applications doivent énumérer explicitement chaque décodeur et matérialiseur concret activé. Toute nouvelle surface instructionnelle dotée d’un `EventMaterializer` doit être ajoutée au registre applicatif et couverte par un test d’inventaire ordonné ; une crate présente dans le workspace ou dans `kb_pipeline` n’est pas activée automatiquement. Les matérialiseurs exclusivement stateful qui n’implémentent pas `EventMaterializer` restent routés par leurs APIs de snapshots dédiées. +- Les registres de composition runtime des applications doivent énumérer explicitement chaque décodeur et matérialiseur concret activé. Toute nouvelle surface instructionnelle dotée d’un `MtApiEventMaterializer` doit être ajoutée au registre applicatif et couverte par un test d’inventaire ordonné ; une crate présente dans le workspace ou dans `kb_pipeline` n’est pas activée automatiquement. Les matérialiseurs exclusivement stateful qui n’implémentent pas `MtApiEventMaterializer` restent routés par leurs APIs de snapshots dédiées. - Les corrélations instruction/état doivent produire une issue explicite (`confirmed`, `contradicted` ou `not_applicable`) et ne doivent jamais transformer automatiquement une configuration observée en violation, score ou conclusion métier. - Une interface officielle Solana ou SPL étroite doit être préférée à `solana-sdk` lorsque son contrat suffit. - L’ordre de préférence des formats est : schéma officiel `wincode`, schéma officiel Borsh, puis parseur local borné reproduisant exactement le runtime lorsque l’interface officielle n’expose que `bincode`. @@ -244,7 +244,7 @@ Les `program_id` connus doivent être définis une seule fois dans `kb-program-i - Toute API publique portée depuis une ancienne crate doit être réexportée au crate root de `kb-lib`. - `kb-store` regroupe les contrats store-neutral et les adaptateurs de persistance, avec PostgreSQL comme adaptateur de production initial. - `kb-store/src/lib.rs` reste une façade : les DTO, entités, traits, requêtes et implémentations résident dans des modules privés dédiés et toute API publique est réexportée au crate root. -- Les modèles source-neutral partagés avec les décodeurs, notamment `CoreInstructionReplayInput`, appartiennent à `kb-lib`; `kb-store` les consomme et les réexporte sans les dupliquer. +- Les modèles source-neutral partagés avec les décodeurs, notamment `MdCoreInstructionReplayInput`, appartiennent à `kb-lib`; `kb-store` les consomme et les réexporte sans les dupliquer. - `kb-lib` ne dépend jamais de `kb-store`. Cette direction de dépendance évite tout cycle entre modèles, décodage et persistance. - `kb-store` ne dépend pas de `kb-config`. La frontière applicative transforme une configuration résolue en options de store explicitement validées. - Les adaptateurs concrets implémentent les mêmes traits neutres et ne font pas fuiter leurs types de connexion dans les contrats. diff --git a/config/example.config.json b/config/example.config.json index 6868e17..54c1db3 100644 --- a/config/example.config.json +++ b/config/example.config.json @@ -28,7 +28,7 @@ "kb-lib.decoder.spl.elgamal_registry", "kb-lib.decoder.spl.memo", "kb-lib.decoder.spl.token", - "kb-lib.decoder.spl.token_2022", + "kb-lib.decoder.spl.token2022", "kb_execution_solana", "kb_executor_metadata_metaplex_token_metadata", "kb_executor_metadata_spl_name_service", @@ -40,15 +40,15 @@ "kb_executor_spl_noop", "kb_executor_spl_single_pool", "kb_executor_spl_token", - "kb_executor_spl_token_2022", + "kb_executor_spl_token2022", "kb-logging", "kb-lib.materializer.admin", "kb-lib.materializer.compliance", "kb-lib.materializer.lifecycle", - "kb_materializer_risk", + "kb-lib.materializer.risk", "kb-lib.materializer.staking", - "kb_materializer_token_accounts", - "kb_materializer_transaction_annotations", + "kb-lib.materializer.token", + "kb-lib.materializer.transaction", "kb_pipeline", "kb_rpc", "kb-store", @@ -810,42 +810,42 @@ ] }, { - "name": "file_kb_materializer_transaction_annotations_debug", + "name": "file_kb_lib_materializer_transaction_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/devnet/kb_materializer_transaction_annotations/debug.log", + "path": "logs/devnet/kb-lib/materializer/transaction/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { - "name": "file_kb_materializer_transaction_annotations_info", + "name": "file_kb_lib_materializer_transaction_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/devnet/kb_materializer_transaction_annotations/info.log", + "path": "logs/devnet/kb-lib/materializer/transaction/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { - "name": "file_kb_materializer_transaction_annotations_error", + "name": "file_kb_lib_materializer_transaction_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/devnet/kb_materializer_transaction_annotations/error.jsonl", + "path": "logs/devnet/kb-lib/materializer/transaction/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { @@ -1044,120 +1044,120 @@ ] }, { - "name": "file_kb_materializer_token_accounts_debug", + "name": "file_kb_lib_materializer_token_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/devnet/kb_materializer_token_accounts/debug.log", + "path": "logs/devnet/kb-lib/materializer/token/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_token_accounts_info", + "name": "file_kb_lib_materializer_token_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/devnet/kb_materializer_token_accounts/info.log", + "path": "logs/devnet/kb-lib/materializer/token/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_token_accounts_error", + "name": "file_kb_lib_materializer_token_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/devnet/kb_materializer_token_accounts/error.jsonl", + "path": "logs/devnet/kb-lib/materializer/token/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_risk_debug", + "name": "file_kb_lib_materializer_risk_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/devnet/kb_materializer_risk/debug.log", + "path": "logs/devnet/kb-lib/materializer/risk/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_materializer_risk_info", + "name": "file_kb_lib_materializer_risk_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/devnet/kb_materializer_risk/info.log", + "path": "logs/devnet/kb-lib/materializer/risk/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_materializer_risk_error", + "name": "file_kb_lib_materializer_risk_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/devnet/kb_materializer_risk/error.jsonl", + "path": "logs/devnet/kb-lib/materializer/risk/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_debug", + "name": "file_kb_lib_decoder_spl_token2022_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/devnet/kb_lib_decoder_spl_token_2022/debug.log", + "path": "logs/devnet/kb_lib_decoder_spl_token2022/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_info", + "name": "file_kb_lib_decoder_spl_token2022_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/devnet/kb_lib_decoder_spl_token_2022/info.log", + "path": "logs/devnet/kb_lib_decoder_spl_token2022/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_error", + "name": "file_kb_lib_decoder_spl_token2022_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/devnet/kb_lib_decoder_spl_token_2022/error.jsonl", + "path": "logs/devnet/kb_lib_decoder_spl_token2022/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { @@ -1317,42 +1317,42 @@ ] }, { - "name": "file_kb_executor_spl_token_2022_debug", + "name": "file_kb_executor_spl_token2022_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/devnet/kb_executor_spl_token_2022/debug.log", + "path": "logs/devnet/kb_executor_spl_token2022/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] }, { - "name": "file_kb_executor_spl_token_2022_info", + "name": "file_kb_executor_spl_token2022_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/devnet/kb_executor_spl_token_2022/info.log", + "path": "logs/devnet/kb_executor_spl_token2022/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] }, { - "name": "file_kb_executor_spl_token_2022_error", + "name": "file_kb_executor_spl_token2022_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/devnet/kb_executor_spl_token_2022/error.jsonl", + "path": "logs/devnet/kb_executor_spl_token2022/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] } ], @@ -1630,7 +1630,7 @@ "kb-lib.decoder.spl.elgamal_registry", "kb-lib.decoder.spl.memo", "kb-lib.decoder.spl.token", - "kb-lib.decoder.spl.token_2022", + "kb-lib.decoder.spl.token2022", "kb_execution_solana", "kb_executor_metadata_metaplex_token_metadata", "kb_executor_metadata_spl_name_service", @@ -1642,15 +1642,15 @@ "kb_executor_spl_noop", "kb_executor_spl_single_pool", "kb_executor_spl_token", - "kb_executor_spl_token_2022", + "kb_executor_spl_token2022", "kb-logging", "kb-lib.materializer.admin", "kb-lib.materializer.compliance", "kb-lib.materializer.lifecycle", - "kb_materializer_risk", + "kb-lib.materializer.risk", "kb-lib.materializer.staking", - "kb_materializer_token_accounts", - "kb_materializer_transaction_annotations", + "kb-lib.materializer.token", + "kb-lib.materializer.transaction", "kb_pipeline", "kb_rpc", "kb-store", @@ -2412,42 +2412,42 @@ ] }, { - "name": "file_kb_materializer_transaction_annotations_debug", + "name": "file_kb_lib_materializer_transaction_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet_research/kb_materializer_transaction_annotations/debug.log", + "path": "logs/mainnet_research/kb-lib/materializer/transaction/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { - "name": "file_kb_materializer_transaction_annotations_info", + "name": "file_kb_lib_materializer_transaction_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet_research/kb_materializer_transaction_annotations/info.log", + "path": "logs/mainnet_research/kb-lib/materializer/transaction/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { - "name": "file_kb_materializer_transaction_annotations_error", + "name": "file_kb_lib_materializer_transaction_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet_research/kb_materializer_transaction_annotations/error.jsonl", + "path": "logs/mainnet_research/kb-lib/materializer/transaction/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { @@ -2646,120 +2646,120 @@ ] }, { - "name": "file_kb_materializer_token_accounts_debug", + "name": "file_kb_lib_materializer_token_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet_research/kb_materializer_token_accounts/debug.log", + "path": "logs/mainnet_research/kb-lib/materializer/token/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_token_accounts_info", + "name": "file_kb_lib_materializer_token_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet_research/kb_materializer_token_accounts/info.log", + "path": "logs/mainnet_research/kb-lib/materializer/token/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_token_accounts_error", + "name": "file_kb_lib_materializer_token_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet_research/kb_materializer_token_accounts/error.jsonl", + "path": "logs/mainnet_research/kb-lib/materializer/token/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_risk_debug", + "name": "file_kb_lib_materializer_risk_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet_research/kb_materializer_risk/debug.log", + "path": "logs/mainnet_research/kb-lib/materializer/risk/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_materializer_risk_info", + "name": "file_kb_lib_materializer_risk_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet_research/kb_materializer_risk/info.log", + "path": "logs/mainnet_research/kb-lib/materializer/risk/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_materializer_risk_error", + "name": "file_kb_lib_materializer_risk_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet_research/kb_materializer_risk/error.jsonl", + "path": "logs/mainnet_research/kb-lib/materializer/risk/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_debug", + "name": "file_kb_lib_decoder_spl_token2022_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet_research/kb_lib_decoder_spl_token_2022/debug.log", + "path": "logs/mainnet_research/kb_lib_decoder_spl_token2022/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_info", + "name": "file_kb_lib_decoder_spl_token2022_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet_research/kb_lib_decoder_spl_token_2022/info.log", + "path": "logs/mainnet_research/kb_lib_decoder_spl_token2022/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_error", + "name": "file_kb_lib_decoder_spl_token2022_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet_research/kb_lib_decoder_spl_token_2022/error.jsonl", + "path": "logs/mainnet_research/kb_lib_decoder_spl_token2022/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { @@ -2919,42 +2919,42 @@ ] }, { - "name": "file_kb_executor_spl_token_2022_debug", + "name": "file_kb_executor_spl_token2022_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet_research/kb_executor_spl_token_2022/debug.log", + "path": "logs/mainnet_research/kb_executor_spl_token2022/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] }, { - "name": "file_kb_executor_spl_token_2022_info", + "name": "file_kb_executor_spl_token2022_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet_research/kb_executor_spl_token_2022/info.log", + "path": "logs/mainnet_research/kb_executor_spl_token2022/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] }, { - "name": "file_kb_executor_spl_token_2022_error", + "name": "file_kb_executor_spl_token2022_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet_research/kb_executor_spl_token_2022/error.jsonl", + "path": "logs/mainnet_research/kb_executor_spl_token2022/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] } ], @@ -3432,7 +3432,7 @@ "kb-lib.decoder.spl.elgamal_registry", "kb-lib.decoder.spl.memo", "kb-lib.decoder.spl.token", - "kb-lib.decoder.spl.token_2022", + "kb-lib.decoder.spl.token2022", "kb_execution_solana", "kb_executor_metadata_metaplex_token_metadata", "kb_executor_metadata_spl_name_service", @@ -3444,15 +3444,15 @@ "kb_executor_spl_noop", "kb_executor_spl_single_pool", "kb_executor_spl_token", - "kb_executor_spl_token_2022", + "kb_executor_spl_token2022", "kb-logging", "kb-lib.materializer.admin", "kb-lib.materializer.compliance", "kb-lib.materializer.lifecycle", - "kb_materializer_risk", + "kb-lib.materializer.risk", "kb-lib.materializer.staking", - "kb_materializer_token_accounts", - "kb_materializer_transaction_annotations", + "kb-lib.materializer.token", + "kb-lib.materializer.transaction", "kb_pipeline", "kb_rpc", "kb-store", @@ -4214,42 +4214,42 @@ ] }, { - "name": "file_kb_materializer_transaction_annotations_debug", + "name": "file_kb_lib_materializer_transaction_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet/kb_materializer_transaction_annotations/debug.log", + "path": "logs/mainnet/kb-lib/materializer/transaction/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { - "name": "file_kb_materializer_transaction_annotations_info", + "name": "file_kb_lib_materializer_transaction_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet/kb_materializer_transaction_annotations/info.log", + "path": "logs/mainnet/kb-lib/materializer/transaction/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { - "name": "file_kb_materializer_transaction_annotations_error", + "name": "file_kb_lib_materializer_transaction_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet/kb_materializer_transaction_annotations/error.jsonl", + "path": "logs/mainnet/kb-lib/materializer/transaction/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_transaction_annotations" + "kb-lib.materializer.transaction" ] }, { @@ -4448,120 +4448,120 @@ ] }, { - "name": "file_kb_materializer_token_accounts_debug", + "name": "file_kb_lib_materializer_token_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet/kb_materializer_token_accounts/debug.log", + "path": "logs/mainnet/kb-lib/materializer/token/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_token_accounts_info", + "name": "file_kb_lib_materializer_token_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet/kb_materializer_token_accounts/info.log", + "path": "logs/mainnet/kb-lib/materializer/token/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_token_accounts_error", + "name": "file_kb_lib_materializer_token_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet/kb_materializer_token_accounts/error.jsonl", + "path": "logs/mainnet/kb-lib/materializer/token/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_token_accounts" + "kb-lib.materializer.token" ] }, { - "name": "file_kb_materializer_risk_debug", + "name": "file_kb_lib_materializer_risk_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet/kb_materializer_risk/debug.log", + "path": "logs/mainnet/kb-lib/materializer/risk/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_materializer_risk_info", + "name": "file_kb_lib_materializer_risk_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet/kb_materializer_risk/info.log", + "path": "logs/mainnet/kb-lib/materializer/risk/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_materializer_risk_error", + "name": "file_kb_lib_materializer_risk_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet/kb_materializer_risk/error.jsonl", + "path": "logs/mainnet/kb-lib/materializer/risk/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_materializer_risk" + "kb-lib.materializer.risk" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_debug", + "name": "file_kb_lib_decoder_spl_token2022_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet/kb_lib_decoder_spl_token_2022/debug.log", + "path": "logs/mainnet/kb_lib_decoder_spl_token2022/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_info", + "name": "file_kb_lib_decoder_spl_token2022_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet/kb_lib_decoder_spl_token_2022/info.log", + "path": "logs/mainnet/kb_lib_decoder_spl_token2022/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { - "name": "file_kb_lib_decoder_spl_token_2022_error", + "name": "file_kb_lib_decoder_spl_token2022_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet/kb_lib_decoder_spl_token_2022/error.jsonl", + "path": "logs/mainnet/kb_lib_decoder_spl_token2022/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb-lib.decoder.spl.token_2022" + "kb-lib.decoder.spl.token2022" ] }, { @@ -4721,42 +4721,42 @@ ] }, { - "name": "file_kb_executor_spl_token_2022_debug", + "name": "file_kb_executor_spl_token2022_debug", "enabled": true, "sink": "file", "level": "debug", - "path": "logs/mainnet/kb_executor_spl_token_2022/debug.log", + "path": "logs/mainnet/kb_executor_spl_token2022/debug.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] }, { - "name": "file_kb_executor_spl_token_2022_info", + "name": "file_kb_executor_spl_token2022_info", "enabled": true, "sink": "file", "level": "info", - "path": "logs/mainnet/kb_executor_spl_token_2022/info.log", + "path": "logs/mainnet/kb_executor_spl_token2022/info.log", "rotation": "daily", "format": "human", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] }, { - "name": "file_kb_executor_spl_token_2022_error", + "name": "file_kb_executor_spl_token2022_error", "enabled": true, "sink": "file", "level": "error", - "path": "logs/mainnet/kb_executor_spl_token_2022/error.jsonl", + "path": "logs/mainnet/kb_executor_spl_token2022/error.jsonl", "rotation": "daily", "format": "json", "ansi": false, "targets": [ - "kb_executor_spl_token_2022" + "kb_executor_spl_token2022" ] } ], diff --git a/docs/CORE_EXTRACTION_CONTRACTS.md b/docs/CORE_EXTRACTION_CONTRACTS.md index 1a06582..7c86a12 100644 --- a/docs/CORE_EXTRACTION_CONTRACTS.md +++ b/docs/CORE_EXTRACTION_CONTRACTS.md @@ -1,5 +1,5 @@ - + # Contrats d’extraction core Solana @@ -38,8 +38,8 @@ L’extraction refuse explicitement : - un `canonical_json` absent ; - un `canonical_json_hash` absent ; -- une version différente de `CANONICAL_TRANSACTION_FORMAT_VERSION` ; -- un JSON non désérialisable en `CanonicalTransaction` ; +- une version différente de `MD_CANONICAL_TRANSACTION_FORMAT_VERSION` ; +- un JSON non désérialisable en `MdCanonicalTransaction` ; - une signature ou un slot différent de la ligne raw ; - un hash recalculé différent du hash stocké ; - un indice de programme ou de compte hors de l’espace résolu. diff --git a/docs/CORE_PROGRAM_IDS.md b/docs/CORE_PROGRAM_IDS.md index 7374b9b..14798f3 100644 --- a/docs/CORE_PROGRAM_IDS.md +++ b/docs/CORE_PROGRAM_IDS.md @@ -14,50 +14,50 @@ Ce fichier sépare les identifiants primitifs Solana/SPL du registre des surface ## Table de contrôle -| Canonique | Program ID | Source | Type | Crate cible | Statut | -|--------------------------------------------|------------------------------------------------|-----------------------------------|----------------------|-------------------------------------------|-------------------------------------| -| `core_solana_address_lookup_table_v1` | `AddressLookupTab1e1111111111111111111111111` | `address_lookup_table` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_bpf_loader_deprecated_v1` | `BPFLoader1111111111111111111111111111111111` | `bpf_loader_deprecated` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_bpf_loader_v2` | `BPFLoader2111111111111111111111111111111111` | `bpf_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_bpf_loader_upgradeable_v1` | `BPFLoaderUpgradeab1e11111111111111111111111` | `bpf_loader_upgradeable` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_compute_budget_v1` | `ComputeBudget111111111111111111111111111111` | `compute_budget` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_config_v1` | `Config1111111111111111111111111111111111111` | `config` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_ed25519_v1` | `Ed25519SigVerify111111111111111111111111111` | `ed25519` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_feature_v1` | `Feature111111111111111111111111111111111111` | `feature` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_incinerator_v1` | `1nc1nerator11111111111111111111111111111111` | `incinerator` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_loader_v4` | `LoaderV411111111111111111111111111111111111` | `loader_v4` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_native_loader_v1` | `NativeLoader1111111111111111111111111111111` | `native_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_secp256k1_v1` | `KeccakSecp256k11111111111111111111111111111` | `secp256k1` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_secp256r1_v1` | `Secp256r1SigVerify1111111111111111111111111` | `secp256r1` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_slashing_v1` | `S1ashing11111111111111111111111111111111111` | `slashing` | `stateless_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_stake_config_v1` | `StakeConfig11111111111111111111111111111111` | `stake_config` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_stake_v1` | `Stake11111111111111111111111111111111111111` | `stake` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_system_v1` | `11111111111111111111111111111111` | `system` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_sysvar_clock_v1` | `SysvarC1ock11111111111111111111111111111111` | `sysvar_clock` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_epoch_rewards_v1` | `SysvarEpochRewards1111111111111111111111111` | `sysvar_epoch_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_epoch_schedule_v1` | `SysvarEpochSchedu1e111111111111111111111111` | `sysvar_epoch_schedule` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_fees_v1` | `SysvarFees111111111111111111111111111111111` | `sysvar_fees` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_instructions_v1` | `Sysvar1nstructions1111111111111111111111111` | `sysvar_instructions` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_last_restart_slot_v1` | `SysvarLastRestartS1ot1111111111111111111111` | `sysvar_last_restart_slot` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_recent_blockhashes_v1` | `SysvarRecentB1ockHashes11111111111111111111` | `sysvar_recent_blockhashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_rent_v1` | `SysvarRent111111111111111111111111111111111` | `sysvar_rent` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_rewards_v1` | `SysvarRewards111111111111111111111111111111` | `sysvar_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_slot_hashes_v1` | `SysvarS1otHashes111111111111111111111111111` | `sysvar_slot_hashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_slot_history_v1` | `SysvarS1otHistory11111111111111111111111111` | `sysvar_slot_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_stake_history_v1` | `SysvarStakeHistory1111111111111111111111111` | `sysvar_stake_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_v1` | `Sysvar1111111111111111111111111111111111111` | `sysvar` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_vote_v1` | `Vote111111111111111111111111111111111111111` | `vote` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_zk_elgamal_proof_v1` | `ZkE1Gama1Proof11111111111111111111111111111` | `zk_elgamal_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_zk_token_proof_v1` | `ZkTokenProof1111111111111111111111111111111` | `zk_token_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_spl_associated_token_account_v1` | `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL` | `associated_token_account` | `program` | `kb_decoder_spl_associated_token_account` | `core_handled` | -| `core_spl_account_compression_v1` | `cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK` | `spl_account_compression` | `program` | `kb_decoder_spl_account_compression` | `core_specialized_reserved_current` | -| `core_spl_memo_v1` | `Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo` | `spl_memo_v1` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | -| `core_spl_memo_v3` | `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` | `spl_memo_v3` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | -| `core_spl_memo_v4` | `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` | `spl_memo_v4` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | -| `core_spl_noop_v1` | `noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV` | `spl_noop` | `program` | `kb_decoder_spl_noop` | `core_specialized_reserved_current` | -| `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` | -| `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` | -| `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` | -| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token_2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | -| `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token_2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` | -| `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` | +| Canonique | Program ID | Source | Type | Crate cible | Statut | +|--------------------------------------------|------------------------------------------------|----------------------------------|----------------------|-------------------------------------------|-------------------------------------| +| `core_solana_address_lookup_table_v1` | `AddressLookupTab1e1111111111111111111111111` | `address_lookup_table` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_bpf_loader_deprecated_v1` | `BPFLoader1111111111111111111111111111111111` | `bpf_loader_deprecated` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_bpf_loader_v2` | `BPFLoader2111111111111111111111111111111111` | `bpf_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_bpf_loader_upgradeable_v1` | `BPFLoaderUpgradeab1e11111111111111111111111` | `bpf_loader_upgradeable` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_compute_budget_v1` | `ComputeBudget111111111111111111111111111111` | `compute_budget` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_config_v1` | `Config1111111111111111111111111111111111111` | `config` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_ed25519_v1` | `Ed25519SigVerify111111111111111111111111111` | `ed25519` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_feature_v1` | `Feature111111111111111111111111111111111111` | `feature` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_incinerator_v1` | `1nc1nerator11111111111111111111111111111111` | `incinerator` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_loader_v4` | `LoaderV411111111111111111111111111111111111` | `loader_v4` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_native_loader_v1` | `NativeLoader1111111111111111111111111111111` | `native_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_secp256k1_v1` | `KeccakSecp256k11111111111111111111111111111` | `secp256k1` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_secp256r1_v1` | `Secp256r1SigVerify1111111111111111111111111` | `secp256r1` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_slashing_v1` | `S1ashing11111111111111111111111111111111111` | `slashing` | `stateless_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_stake_config_v1` | `StakeConfig11111111111111111111111111111111` | `stake_config` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_stake_v1` | `Stake11111111111111111111111111111111111111` | `stake` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_system_v1` | `11111111111111111111111111111111` | `system` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_sysvar_clock_v1` | `SysvarC1ock11111111111111111111111111111111` | `sysvar_clock` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_epoch_rewards_v1` | `SysvarEpochRewards1111111111111111111111111` | `sysvar_epoch_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_epoch_schedule_v1` | `SysvarEpochSchedu1e111111111111111111111111` | `sysvar_epoch_schedule` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_fees_v1` | `SysvarFees111111111111111111111111111111111` | `sysvar_fees` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_instructions_v1` | `Sysvar1nstructions1111111111111111111111111` | `sysvar_instructions` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_last_restart_slot_v1` | `SysvarLastRestartS1ot1111111111111111111111` | `sysvar_last_restart_slot` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_recent_blockhashes_v1` | `SysvarRecentB1ockHashes11111111111111111111` | `sysvar_recent_blockhashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_rent_v1` | `SysvarRent111111111111111111111111111111111` | `sysvar_rent` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_rewards_v1` | `SysvarRewards111111111111111111111111111111` | `sysvar_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_slot_hashes_v1` | `SysvarS1otHashes111111111111111111111111111` | `sysvar_slot_hashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_slot_history_v1` | `SysvarS1otHistory11111111111111111111111111` | `sysvar_slot_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_stake_history_v1` | `SysvarStakeHistory1111111111111111111111111` | `sysvar_stake_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_v1` | `Sysvar1111111111111111111111111111111111111` | `sysvar` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_vote_v1` | `Vote111111111111111111111111111111111111111` | `vote` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_zk_elgamal_proof_v1` | `ZkE1Gama1Proof11111111111111111111111111111` | `zk_elgamal_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_zk_token_proof_v1` | `ZkTokenProof1111111111111111111111111111111` | `zk_token_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_spl_associated_token_account_v1` | `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL` | `associated_token_account` | `program` | `kb_decoder_spl_associated_token_account` | `core_handled` | +| `core_spl_account_compression_v1` | `cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK` | `spl_account_compression` | `program` | `kb_decoder_spl_account_compression` | `core_specialized_reserved_current` | +| `core_spl_memo_v1` | `Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo` | `spl_memo_v1` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | +| `core_spl_memo_v3` | `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` | `spl_memo_v3` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | +| `core_spl_memo_v4` | `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` | `spl_memo_v4` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | +| `core_spl_noop_v1` | `noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV` | `spl_noop` | `program` | `kb_decoder_spl_noop` | `core_specialized_reserved_current` | +| `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` | +| `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` | +| `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` | +| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | +| `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` | +| `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` | diff --git a/docs/DECODER_MATERIALIZATION_CONTRACTS.md b/docs/DECODER_MATERIALIZATION_CONTRACTS.md index a50fc64..8b428d9 100644 --- a/docs/DECODER_MATERIALIZATION_CONTRACTS.md +++ b/docs/DECODER_MATERIALIZATION_CONTRACTS.md @@ -20,7 +20,7 @@ core instruction contextualisée ## Input contextualisé -`CoreInstructionReplayInput` reste l’unique contrat d’entrée commun. Son contrat passe à la version `2` dans `0.4.1-pre.014`. Il contient la signature, le slot, le statut et l’erreur on-chain, le chemin stable de l’instruction, le program ID, les comptes résolus dans leur ordre original, le payload brut déterministe et son hash, toutes les instructions outer ordonnées par index numérique, les inner instructions descendantes, les logs reliés prudemment, les changements de balances et la version du contrat core. +`MdCoreInstructionReplayInput` reste l’unique contrat d’entrée commun. Son contrat passe à la version `2` dans `0.4.1-pre.014`. Il contient la signature, le slot, le statut et l’erreur on-chain, le chemin stable de l’instruction, le program ID, les comptes résolus dans leur ordre original, le payload brut déterministe et son hash, toutes les instructions outer ordonnées par index numérique, les inner instructions descendantes, les logs reliés prudemment, les changements de balances et la version du contrat core. `outer_instructions_json` est un tableau stable dont chaque entrée contient `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. L’instruction cible est incluse. Cette projection provient des tables core existantes et ne nécessite aucune migration SQL. @@ -30,7 +30,7 @@ Le passage au contrat `2` modifie légitimement les hashes existants, car les pa ## Contrat de décodeur -`InstructionDecoder` expose : +`DcApiInstructionDecoder` expose : - une identité stable `name/version` ; - les programmes et surfaces supportés ; @@ -58,7 +58,7 @@ observation_committed `observation_committed` doit être faux lorsque la transaction a été annulée. Ces observations peuvent décrire une instruction tentée, un événement loggé avant l’erreur, une classification d’échec, une consommation de compute ou une surface appelée. -Elles ne peuvent pas produire automatiquement un trade réussi, une modification de liquidité réussie, un changement confirmé de catalogue ou une candle normale. `EventMaterializer` applique une politique explicite par famille. Les familles `trade`, `liquidity` et `lifecycle` sont refusées avant l’appel au matérialiseur lorsque la source est échouée ou non commitée. Une seconde barrière valide ensuite les familles de sortie et n’autorise, dans ce contexte, que les matérialisations d’audit ou de risque. +Elles ne peuvent pas produire automatiquement un trade réussi, une modification de liquidité réussie, un changement confirmé de catalogue ou une candle normale. `MtApiEventMaterializer` applique une politique explicite par famille. Les familles `trade`, `liquidity` et `lifecycle` sont refusées avant l’appel au matérialiseur lorsque la source est échouée ou non commitée. Une seconde barrière valide ensuite les familles de sortie et n’autorise, dans ce contexte, que les matérialisations d’audit ou de risque. ## Persistance diff --git a/docs/EXECUTION_MODEL.md b/docs/EXECUTION_MODEL.md index 95cc292..700fd63 100644 --- a/docs/EXECUTION_MODEL.md +++ b/docs/EXECUTION_MODEL.md @@ -77,11 +77,11 @@ Le genesis hash sert à classifier les clusters publics connus. Le réseau de pr La simulation accepte une transaction base64 non signée lorsque `sigVerify = false`; `replaceRecentBlockhash = true` permet au nœud de remplacer le blockhash avant simulation. Les erreurs runtime restent un résultat de simulation typé et ne sont pas confondues avec une erreur HTTP ou JSON-RPC. -`kb_rpc` ne fabrique pas le contexte de sécurité : cluster attendu, âge du blockhash, nonce account et nonce authority sont fournis explicitement lors de la conversion vers `ExecutionSimulationResult`. Depuis `pre.013`, `getAccountInfo` possède aussi un mode données complètes borné : le mode metadata-only conserve `dataSlice.length = 0`, tandis que `confirmed_with_data(max_data_bytes)` exige un tuple base64 complet dont la longueur décodée égale `space`. +`kb_rpc` ne fabrique pas le contexte de sécurité : cluster attendu, âge du blockhash, nonce account et nonce authority sont fournis explicitement lors de la conversion vers `ExApiExecutionSimulationResult`. Depuis `pre.013`, `getAccountInfo` possède aussi un mode données complètes borné : le mode metadata-only conserve `dataSlice.length = 0`, tandis que `confirmed_with_data(max_data_bytes)` exige un tuple base64 complet dont la longueur décodée égale `space`. ## Assemblage et signature Solana -`0.4.2-pre.005` introduit `kb_execution_solana`, frontière commune entre les exécuteurs et les adaptateurs RPC. La crate convertit les `PlannedInstruction` en instructions SDK, compile le message avec son fee payer et sa source de blockhash, puis vérifie que les signataires réellement compilés correspondent exactement au contrat du plan. +`0.4.2-pre.005` introduit `kb_execution_solana`, frontière commune entre les exécuteurs et les adaptateurs RPC. La crate convertit les `ExApiPlannedInstruction` en instructions SDK, compile le message avec son fee payer et sa source de blockhash, puis vérifie que les signataires réellement compilés correspondent exactement au contrat du plan. La transaction non signée fournit deux sorties distinctes : diff --git a/docs/INSTRUCTION_REPLAY_CONTRACTS.md b/docs/INSTRUCTION_REPLAY_CONTRACTS.md index 6204d21..1a9d148 100644 --- a/docs/INSTRUCTION_REPLAY_CONTRACTS.md +++ b/docs/INSTRUCTION_REPLAY_CONTRACTS.md @@ -50,7 +50,7 @@ Certains protocoles Solana exigent de lire : - des séquences de logs liées à un CPI ; - des instructions voisines de la même transaction. -`CoreInstructionReplayInput` représente ce contrat de lecture : une instruction ciblée plus un contexte extrait depuis les tables `core`. Depuis le contrat `2`, ce contexte inclut également toutes les instructions outer de la signature, ordonnées numériquement et munies de leur payload retenu et de son hash. +`MdCoreInstructionReplayInput` représente ce contrat de lecture : une instruction ciblée plus un contexte extrait depuis les tables `core`. Depuis le contrat `2`, ce contexte inclut également toutes les instructions outer de la signature, ordonnées numériquement et munies de leur payload retenu et de son hash. ## Sélection de replay @@ -68,7 +68,7 @@ program_id = programme ciblé par le décodeur plage de slots = optionnelle ``` -Le repository charge les logs, balances, account keys et instructions outer nécessaires pour retourner `CoreInstructionReplayInput`. La liste outer inclut la cible et utilise les champs stables `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. Cette extension lit les tables existantes et ne demande aucune migration. +Le repository charge les logs, balances, account keys et instructions outer nécessaires pour retourner `MdCoreInstructionReplayInput`. La liste outer inclut la cible et utilise les champs stables `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. Cette extension lit les tables existantes et ne demande aucune migration. ## Marquage de cycle de vie diff --git a/docs/MATERIALIZATIONS.md b/docs/MATERIALIZATIONS.md index 7914f97..46c12ab 100644 --- a/docs/MATERIALIZATIONS.md +++ b/docs/MATERIALIZATIONS.md @@ -1,5 +1,5 @@ - + # Catalogue des matérialisations @@ -36,16 +36,26 @@ La famille décodée n'impose pas à elle seule la famille matérialisée. `auth `kb_lib::AdminMaterializer` produit des sorties `Admin` pour les assignations System, les écritures Config opaques et les changements d’autorité Loader. `kb_lib::ComplianceAuditMaterializer` produit des sorties `ComplianceAudit` pour les écritures/copies de bytecode Loader. `kb_lib::StakingMaterializer` produit les projections instructionnelles Stake/Vote commitées : comptes stake/vote, autorités, lockup, délégation, vote state, retraits et dépôt de rewards. Les données complètes ne sont jamais recopiées : seules les clés, autorités, offsets, tailles, hashes, préfixes et paramètres bornés disponibles sont conservés. -Les quatre implémentations résident respectivement dans `kb_lib::materializer::lifecycle`, `admin`, `compliance` et `staking`, mais sont réexportées à la racine de `kb-lib`. Les identités de processor historiques restent stables pour les replays ; les targets de tracing utilisent la hiérarchie consolidée `kb-lib.materializer.*`. +Les implémentations résident dans des modules privés et sont réexportées uniquement à la racine de `kb-lib`. Les identités de processor historiques restent stables pour les replays ; les targets de tracing utilisent la hiérarchie consolidée `kb-lib.materializer.*`. Le retrait d'un nonce account conserve une sémantique conditionnelle : le runtime ferme le compte uniquement lorsque la totalité du solde est retirée. La projection décrit l'opération commitée et ne prétend pas reconstruire l'état final transactionnel du compte. Les deltas SOL restent la responsabilité du graphe core. Une preuve ZK n'est jamais matérialisée. Seul le lifecycle du compte de contexte est projeté lorsqu'il existe. Un rapport Slashing conserve le signal de violation et son lifecycle, mais pas le contenu du compte de preuve externe ; `penaltyAppliedByProgram` reste faux car le programme ne retire pas lui-même du stake. L'ancien ZK Token Proof Program reste en decode/audit, car le runtime actuel est sans effet et aucun historique mainnet fiable n'a été observé. +## Projections SPL et Metaplex portées + +- `MtTransactionAnnotationMaterializer` accepte uniquement les observations Memo exactes, réussies et commitées, puis produit une annotation idempotente bornée avec texte, hash, génération et signataires vérifiés. +- `MtTokenAccountsMaterializer` projette les mutations SPL Token classique et Token‑2022, possède le lifecycle ATA et peut produire un snapshot borné Mint/Account/Multisig Token‑2022 à partir de l’état parsé. +- `MtFeesMaterializer` projette les instructions et snapshots de frais Token‑2022 publics ou confidentiels. Les blobs confidentiels restent opaques et `confidentialValuesDecrypted` demeure faux. +- `MtRiskMaterializer` produit uniquement des faits structurels SPL Token/ATA : délégation, freeze/thaw, autorités révoquées, multisig faible et récupération d’ATA imbriquée. Aucun score arbitraire n’est inventé. +- `MtMetadataMaterializer` projette les metadata incorporées Token‑2022 et les comptes Metaplex canoniques, avec provenance et lifecycle explicites. `externalUriFetched` reste faux. + +Le registre ElGamal ne possède pas un matérialiseur autonome : ses snapshots administratifs sont la responsabilité de `MtAdminMaterializer`. Le fetch HTTP/IPFS/Arweave des URI est off-chain et reste réservé à une future crate dédiée. + ## Matérialisations spécialisées à prévoir - `nft` : NFT classiques, programmables et compressés. -- `metadata` : metadata Metaplex, creators, collection, update authority, URI et symbol. +- `metadata` avancée : fetch off-chain borné, réconciliation de provenance et historique des changements. - `oracle` : prix, publisher, confidence, staleness et sources d'oracle. - `lending` : borrow, repay, collateral, liquidation et health factor. - `staking` avancé : snapshots de comptes Stake/Vote avant/après, activation par epoch, crédits Vote cumulés et réconciliation avec sysvars. diff --git a/docs/METAPLEX_TOKEN_METADATA_MATRIX.json b/docs/METAPLEX_TOKEN_METADATA_MATRIX.json index e0c5070..b1e9b41 100644 --- a/docs/METAPLEX_TOKEN_METADATA_MATRIX.json +++ b/docs/METAPLEX_TOKEN_METADATA_MATRIX.json @@ -313,7 +313,7 @@ ], "provenance_boundaries": [ "metaplex_token_metadata", - "token_2022_embedded_metadata", + "token2022_embedded_metadata", "metaplex_core", "metaplex_bubblegum" ], diff --git a/docs/NATIVE_SOLANA_MATERIALIZATION_AUDIT.md b/docs/NATIVE_SOLANA_MATERIALIZATION_AUDIT.md index c428a89..f5745b0 100644 --- a/docs/NATIVE_SOLANA_MATERIALIZATION_AUDIT.md +++ b/docs/NATIVE_SOLANA_MATERIALIZATION_AUDIT.md @@ -11,21 +11,21 @@ Les sorties ne sont pas des snapshots finaux de comptes ou de runtime. Les état ## Projections actives par matérialiseur -| Matérialiseur | Surfaces | Projection | -|------------------------------------|----------------------|---------------------------------------------------------------------------------------------------------------------| -| `LifecycleMaterializer` | Address Lookup Table | lifecycle create/freeze/extend/deactivate/close | -| `LifecycleMaterializer` | Feature | révocation de feature gate | -| `LifecycleMaterializer` | Loaders | déploiement, finalisation et transitions lifecycle stables | -| `LifecycleMaterializer` | System | durable nonce, create account et allocate | -| `LifecycleMaterializer` | ZK ElGamal | création ou fermeture d’un compte de contexte | -| `LifecycleMaterializer` | Slashing | initialisation ou fermeture d’un rapport de violation | -| `AdminMaterializer` | System | assign et assign with seed | -| `AdminMaterializer` | Config | écriture opaque bornée avec clés, taille, SHA-256 et préfixe | -| `AdminMaterializer` | Loaders | changements d’autorité | -| `ComplianceAuditMaterializer` | Loaders | écritures/copies de bytecode bornées par offsets, tailles, SHA-256 et préfixes | -| `ComplianceAuditMaterializer` | Compute Budget | profil transactionnel agrégé, last-write-wins, une seule sortie par transaction | -| `StakingMaterializer` | Stake | compte, délégation, désactivation, split, merge, withdraw, move stake/lamports, autorités et lockup instructionnels | -| `StakingMaterializer` | Vote | compte, autorités, identité, commission, vote state, retraits et dépôt de rewards instructionnels | +| Matérialiseur | Surfaces | Projection | +|---------------------------------|----------------------|---------------------------------------------------------------------------------------------------------------------| +| `MtLifecycleMaterializer` | Address Lookup Table | lifecycle create/freeze/extend/deactivate/close | +| `MtLifecycleMaterializer` | Feature | révocation de feature gate | +| `MtLifecycleMaterializer` | Loaders | déploiement, finalisation et transitions lifecycle stables | +| `MtLifecycleMaterializer` | System | durable nonce, create account et allocate | +| `MtLifecycleMaterializer` | ZK ElGamal | création ou fermeture d’un compte de contexte | +| `MtLifecycleMaterializer` | Slashing | initialisation ou fermeture d’un rapport de violation | +| `MtAdminMaterializer` | System | assign et assign with seed | +| `MtAdminMaterializer` | Config | écriture opaque bornée avec clés, taille, SHA-256 et préfixe | +| `MtAdminMaterializer` | Loaders | changements d’autorité | +| `MtComplianceAuditMaterializer` | Loaders | écritures/copies de bytecode bornées par offsets, tailles, SHA-256 et préfixes | +| `MtComplianceAuditMaterializer` | Compute Budget | profil transactionnel agrégé, last-write-wins, une seule sortie par transaction | +| `MtStakingMaterializer` | Stake | compte, délégation, désactivation, split, merge, withdraw, move stake/lamports, autorités et lockup instructionnels | +| `MtStakingMaterializer` | Vote | compte, autorités, identité, commission, vote state, retraits et dépôt de rewards instructionnels | ## Politique des transactions échouées diff --git a/docs/PROGRAM_REGISTRY_CONTROL.md b/docs/PROGRAM_REGISTRY_CONTROL.md index 036c144..8dfb277 100644 --- a/docs/PROGRAM_REGISTRY_CONTROL.md +++ b/docs/PROGRAM_REGISTRY_CONTROL.md @@ -54,52 +54,52 @@ Nouvelle règle : Ces identifiants sont détaillés dans `docs/CORE_PROGRAM_IDS.md`. Ils sont couverts par les décodeurs core/primitifs ou par des crates spécialisées SPL futures, pas par une crate DEX dédiée. -| Canonique | Program ID | Source | Type | Crate cible | Statut | -|--------------------------------------------|------------------------------------------------|-----------------------------------|----------------------|-------------------------------------------|-------------------------------------| -| `core_solana_address_lookup_table_v1` | `AddressLookupTab1e1111111111111111111111111` | `address_lookup_table` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_bpf_loader_deprecated_v1` | `BPFLoader1111111111111111111111111111111111` | `bpf_loader_deprecated` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_bpf_loader_v2` | `BPFLoader2111111111111111111111111111111111` | `bpf_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_bpf_loader_upgradeable_v1` | `BPFLoaderUpgradeab1e11111111111111111111111` | `bpf_loader_upgradeable` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_compute_budget_v1` | `ComputeBudget111111111111111111111111111111` | `compute_budget` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_config_v1` | `Config1111111111111111111111111111111111111` | `config` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_ed25519_v1` | `Ed25519SigVerify111111111111111111111111111` | `ed25519` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_feature_v1` | `Feature111111111111111111111111111111111111` | `feature` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_incinerator_v1` | `1nc1nerator11111111111111111111111111111111` | `incinerator` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_loader_v4` | `LoaderV411111111111111111111111111111111111` | `loader_v4` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_native_loader_v1` | `NativeLoader1111111111111111111111111111111` | `native_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_secp256k1_v1` | `KeccakSecp256k11111111111111111111111111111` | `secp256k1` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_secp256r1_v1` | `Secp256r1SigVerify1111111111111111111111111` | `secp256r1` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_stake_config_v1` | `StakeConfig11111111111111111111111111111111` | `stake_config` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_stake_v1` | `Stake11111111111111111111111111111111111111` | `stake` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_system_v1` | `11111111111111111111111111111111` | `system` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_sysvar_clock_v1` | `SysvarC1ock11111111111111111111111111111111` | `sysvar_clock` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_epoch_rewards_v1` | `SysvarEpochRewards1111111111111111111111111` | `sysvar_epoch_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_epoch_schedule_v1` | `SysvarEpochSchedu1e111111111111111111111111` | `sysvar_epoch_schedule` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_fees_v1` | `SysvarFees111111111111111111111111111111111` | `sysvar_fees` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_instructions_v1` | `Sysvar1nstructions1111111111111111111111111` | `sysvar_instructions` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_last_restart_slot_v1` | `SysvarLastRestartS1ot1111111111111111111111` | `sysvar_last_restart_slot` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_recent_blockhashes_v1` | `SysvarRecentB1ockHashes11111111111111111111` | `sysvar_recent_blockhashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_rent_v1` | `SysvarRent111111111111111111111111111111111` | `sysvar_rent` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_rewards_v1` | `SysvarRewards111111111111111111111111111111` | `sysvar_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_slot_hashes_v1` | `SysvarS1otHashes111111111111111111111111111` | `sysvar_slot_hashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_slot_history_v1` | `SysvarS1otHistory11111111111111111111111111` | `sysvar_slot_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_stake_history_v1` | `SysvarStakeHistory1111111111111111111111111` | `sysvar_stake_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_sysvar_v1` | `Sysvar1111111111111111111111111111111111111` | `sysvar` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | -| `core_solana_vote_v1` | `Vote111111111111111111111111111111111111111` | `vote` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_zk_elgamal_proof_v1` | `ZkE1Gama1Proof11111111111111111111111111111` | `zk_elgamal_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_solana_zk_token_proof_v1` | `ZkTokenProof1111111111111111111111111111111` | `zk_token_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | -| `core_spl_associated_token_account_v1` | `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL` | `associated_token_account` | `program` | `kb_decoder_spl_associated_token_account` | `core_handled` | -| `core_spl_account_compression_v1` | `cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK` | `spl_account_compression` | `program` | `kb_decoder_spl_account_compression` | `core_specialized_reserved_current` | -| `core_spl_memo_v1` | `Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo` | `spl_memo_v1` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | -| `core_spl_memo_v3` | `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` | `spl_memo_v3` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | -| `core_spl_memo_v4` | `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` | `spl_memo_v4` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | -| `core_spl_noop_v1` | `noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV` | `spl_noop` | `program` | `kb_decoder_spl_noop` | `core_specialized_reserved_current` | -| `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` | -| `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` | -| `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` | -| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token_2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | -| `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token_2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` | -| `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` | +| Canonique | Program ID | Source | Type | Crate cible | Statut | +|--------------------------------------------|------------------------------------------------|----------------------------------|----------------------|-------------------------------------------|-------------------------------------| +| `core_solana_address_lookup_table_v1` | `AddressLookupTab1e1111111111111111111111111` | `address_lookup_table` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_bpf_loader_deprecated_v1` | `BPFLoader1111111111111111111111111111111111` | `bpf_loader_deprecated` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_bpf_loader_v2` | `BPFLoader2111111111111111111111111111111111` | `bpf_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_bpf_loader_upgradeable_v1` | `BPFLoaderUpgradeab1e11111111111111111111111` | `bpf_loader_upgradeable` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_compute_budget_v1` | `ComputeBudget111111111111111111111111111111` | `compute_budget` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_config_v1` | `Config1111111111111111111111111111111111111` | `config` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_ed25519_v1` | `Ed25519SigVerify111111111111111111111111111` | `ed25519` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_feature_v1` | `Feature111111111111111111111111111111111111` | `feature` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_incinerator_v1` | `1nc1nerator11111111111111111111111111111111` | `incinerator` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_loader_v4` | `LoaderV411111111111111111111111111111111111` | `loader_v4` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_native_loader_v1` | `NativeLoader1111111111111111111111111111111` | `native_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_secp256k1_v1` | `KeccakSecp256k11111111111111111111111111111` | `secp256k1` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_secp256r1_v1` | `Secp256r1SigVerify1111111111111111111111111` | `secp256r1` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_stake_config_v1` | `StakeConfig11111111111111111111111111111111` | `stake_config` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_stake_v1` | `Stake11111111111111111111111111111111111111` | `stake` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_system_v1` | `11111111111111111111111111111111` | `system` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_sysvar_clock_v1` | `SysvarC1ock11111111111111111111111111111111` | `sysvar_clock` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_epoch_rewards_v1` | `SysvarEpochRewards1111111111111111111111111` | `sysvar_epoch_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_epoch_schedule_v1` | `SysvarEpochSchedu1e111111111111111111111111` | `sysvar_epoch_schedule` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_fees_v1` | `SysvarFees111111111111111111111111111111111` | `sysvar_fees` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_instructions_v1` | `Sysvar1nstructions1111111111111111111111111` | `sysvar_instructions` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_last_restart_slot_v1` | `SysvarLastRestartS1ot1111111111111111111111` | `sysvar_last_restart_slot` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_recent_blockhashes_v1` | `SysvarRecentB1ockHashes11111111111111111111` | `sysvar_recent_blockhashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_rent_v1` | `SysvarRent111111111111111111111111111111111` | `sysvar_rent` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_rewards_v1` | `SysvarRewards111111111111111111111111111111` | `sysvar_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_slot_hashes_v1` | `SysvarS1otHashes111111111111111111111111111` | `sysvar_slot_hashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_slot_history_v1` | `SysvarS1otHistory11111111111111111111111111` | `sysvar_slot_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_stake_history_v1` | `SysvarStakeHistory1111111111111111111111111` | `sysvar_stake_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_sysvar_v1` | `Sysvar1111111111111111111111111111111111111` | `sysvar` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` | +| `core_solana_vote_v1` | `Vote111111111111111111111111111111111111111` | `vote` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_zk_elgamal_proof_v1` | `ZkE1Gama1Proof11111111111111111111111111111` | `zk_elgamal_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_solana_zk_token_proof_v1` | `ZkTokenProof1111111111111111111111111111111` | `zk_token_proof` | `program` | `kb_decoder_solana_core` | `core_handled` | +| `core_spl_associated_token_account_v1` | `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL` | `associated_token_account` | `program` | `kb_decoder_spl_associated_token_account` | `core_handled` | +| `core_spl_account_compression_v1` | `cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK` | `spl_account_compression` | `program` | `kb_decoder_spl_account_compression` | `core_specialized_reserved_current` | +| `core_spl_memo_v1` | `Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo` | `spl_memo_v1` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | +| `core_spl_memo_v3` | `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` | `spl_memo_v3` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | +| `core_spl_memo_v4` | `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` | `spl_memo_v4` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` | +| `core_spl_noop_v1` | `noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV` | `spl_noop` | `program` | `kb_decoder_spl_noop` | `core_specialized_reserved_current` | +| `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` | +| `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` | +| `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` | +| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | +| `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` | +| `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` | ## DEX, AMM, CPMM, CLMM, DLMM, stable swap, weighted swap et orderbooks @@ -245,15 +245,15 @@ Ces identifiants sont détaillés dans `docs/CORE_PROGRAM_IDS.md`. Ils sont couv ## NFT, metadata, admin, governance et locks -| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut | -|------------------------------------|------------------------------------------------|---------------------------|---------------------------|------------------------|-----------------------------------------------|--------------------| -| `lock_raydium_lp` | `LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE` | `raydium_lock_lp` | `raydium_lock_lp` | `-` | `kb_decoder_lock_raydium_lp` | `reserved_missing` | -| `admin_jupiter_lock` | `LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn` | `jupiter_lock` | `jupiter_lock` | `-` | `kb_decoder_admin_jupiter_lock` | `reserved_missing` | -| `admin_pump_fees` | `pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ` | `pump_fees` | `pump_fees` | `kb_decoder_pump_fees` | `kb_decoder_admin_pump_fees` | `current_alias` | +| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut | +|------------------------------------|------------------------------------------------|---------------------------|---------------------------|------------------------|------------------------------------------------------|--------------------| +| `lock_raydium_lp` | `LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE` | `raydium_lock_lp` | `raydium_lock_lp` | `-` | `kb_decoder_lock_raydium_lp` | `reserved_missing` | +| `admin_jupiter_lock` | `LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn` | `jupiter_lock` | `jupiter_lock` | `-` | `kb_decoder_admin_jupiter_lock` | `reserved_missing` | +| `admin_pump_fees` | `pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ` | `pump_fees` | `pump_fees` | `kb_decoder_pump_fees` | `kb_decoder_admin_pump_fees` | `current_alias` | | `metadata_metaplex_token_metadata` | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | `metaplex_token_metadata` | `metaplex_token_metadata` | `-` | `kb_lib::decoder::metadata::metaplex_token_metadata` | `current_migrated` | -| `metadata_name_service` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `name_service` | `name_service` | `-` | `kb_decoder_metadata_spl_name_service` | `reserved_missing` | -| `nft_metaplex_bubblegum` | `BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY` | `bubblegum` | `bubblegum` | `-` | `kb_decoder_nft_metaplex_bubblegum` | `reserved_missing` | -| `nft_metaplex_mpl_core` | `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d` | `mpl_core` | `mpl_core` | `-` | `kb_decoder_nft_metaplex_mpl_core` | `reserved_missing` | +| `metadata_name_service` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `name_service` | `name_service` | `-` | `kb_decoder_metadata_spl_name_service` | `reserved_missing` | +| `nft_metaplex_bubblegum` | `BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY` | `bubblegum` | `bubblegum` | `-` | `kb_decoder_nft_metaplex_bubblegum` | `reserved_missing` | +| `nft_metaplex_mpl_core` | `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d` | `mpl_core` | `mpl_core` | `-` | `kb_decoder_nft_metaplex_mpl_core` | `reserved_missing` | ## Surfaces à classifier diff --git a/docs/RUST_WORKSPACE_RULE_AUDIT.md b/docs/RUST_WORKSPACE_RULE_AUDIT.md index 83206a2..8be870f 100644 --- a/docs/RUST_WORKSPACE_RULE_AUDIT.md +++ b/docs/RUST_WORKSPACE_RULE_AUDIT.md @@ -229,7 +229,7 @@ La mise en conformité est découpée avant toute nouvelle prérelease : 1. `pre.035-delta-fix-002` : séparation des règles et audit automatisé reproductible ; 2. correctifs suivants : points d'entrée de crates, réexports `pub`/`pub(crate)`, rustdocs et chemins `crate::...` ; 3. correctifs suivants : imports de traits et suppression des imports ordinaires/groupés ; -4. correctifs suivants : `TRACING_TARGET`, dépendances `tracing`, macros et matrice de routes ; +4. correctifs suivants : `DC_METADATA_MTM_TRACING_TARGET`, dépendances `tracing`, macros et matrice de routes ; 5. correctifs suivants : helpers dupliqués et mutualisation inter-crates ; 6. fermeture : `cargo fmt --all`, audit strict, tests workspace et Clippy global. diff --git a/docs/SOLANA_INTERFACE_DEPENDENCIES.md b/docs/SOLANA_INTERFACE_DEPENDENCIES.md index 96b1062..2cbefa7 100644 --- a/docs/SOLANA_INTERFACE_DEPENDENCIES.md +++ b/docs/SOLANA_INTERFACE_DEPENDENCIES.md @@ -71,7 +71,7 @@ Le message à signer provient de `solana_transaction::Transaction::message_data( ## Identifiants natifs, Vote et loaders dans l’exécuteur -`solana-sdk-ids` est conservé intentionnellement comme registre officiel modulaire des adresses natives et sysvars. Les chemins `solana_sdk_ids::sysvar::{clock,rent,slot_hashes,instructions}` ne constituent pas un retour au SDK monolithique : ils fournissent uniquement des `Pubkey` canoniques. `solana-instructions-sysvar` ne doit être ajouté que lorsqu’une crate appelle réellement ses fonctions d’introspection d’instructions, pas pour remplacer un simple ID officiel. +`solana-sdk-ids` est conservé intentionnellement comme registre officiel modulaire des adresses natives et sysvars. Les chemins `solana_sdk_ids::sysvar::{clock,rent,slot_hashes,instructions}` ne constituent pas un retour au SDK monolithique : ils fournissent uniquement des `MdPubkey` canoniques. `solana-instructions-sysvar` ne doit être ajouté que lorsqu’une crate appelle réellement ses fonctions d’introspection d’instructions, pas pour remplacer un simple ID officiel. `kb_executor_solana_core` consomme `solana-vote-interface ^6.0` avec `serde` et `wincode` pour construire les vingt variantes wire Vote actuelles. Il utilise `solana-instruction` pour `Instruction`/`AccountMeta`, `solana-pubkey::Pubkey` pour les adresses publiques, `solana-hash::Hash` pour les hashes et `solana-sdk-ids` pour Rent, Clock et SlotHashes. Les quatre créations composées utilisent `solana-system-interface`; aucune dépendance `solana-sdk` ni feature `bincode` n’est ajoutée à la crate. @@ -214,7 +214,7 @@ longueurs de chaînes de `Initialize`, `UpdateField` et `RemoveKey`. Cette garde normative pour le décodeur ; `UpdateAuthority` et `Emit` restent sans chaîne. La migration `0.1.0-pre.008` conserve ces contrats dans -`kb_lib::decoder::spl::token_2022` et isole le registre dans +`kb_lib::decoder::spl::token2022` et isole le registre dans `kb_lib::decoder::spl::elgamal_registry`. Les targets de tracing, matrices et Program IDs restent distincts ; aucun pointeur TLV n’est interprété comme une preuve de l’état du programme externe pointé. diff --git a/docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json b/docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json index da78d8b..2d5f70f 100644 --- a/docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json +++ b/docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json @@ -1,13 +1,17 @@ { "file": "docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json", - "version": 10, + "version": 11, "schemaVersion": 1, "bot3Migration": { "target": "kb-lib.decoder.spl.associated_token_account", - "status": "ported_pending_operator_cargo_validation", + "status": "decoder_operator_validated_materializers_ported", "prerelease": "0.1.0-pre.007", "preservedDifferentialTests": 10, - "materializerPorted": false, + "materializerPorted": true, + "publicMaterializers": [ + "kb_lib::TokenAccountsMaterializer", + "kb_lib::RiskMaterializer" + ], "executorPorted": false, "pipelinePorted": false }, @@ -15,7 +19,7 @@ "systemProgramId": "11111111111111111111111111111111", "supportedTokenPrograms": [ {"code": "spl_token", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "scope": "classic_token_account_lifecycle_only"}, - {"code": "spl_token_2022", "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "scope": "ata_lifecycle_only_without_general_token_2022_instruction_or_extension_decode"} + {"code": "spl_token2022", "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "scope": "ata_lifecycle_only_without_general_token2022_instruction_or_extension_decode"} ], "interface": { "workspaceConstraint": "^2.0", @@ -85,10 +89,10 @@ "runtimeRules": ["fails if the associated account already exists", "funding account pays rent and creation cost", "mint and created account must be coherent with the selected token program"], "event": "spl_associated_token_account.create", "authorizedProjections": ["token_accounts:ata_created"], - "forbiddenProjections": ["token_balance_snapshot", "duplicate_spl_token_initialize_account_cpi", "token_2022_extension_fact"], + "forbiddenProjections": ["token_balance_snapshot", "duplicate_spl_token_initialize_account_cpi", "token2022_extension_fact"], "officialBuilder": {"available": true, "function": "create_associated_token_account", "canonicalWireOnly": true}, "executorSupport": {"status": "supported", "operationCode": "spl_associated_token_account.create", "builder": "create_associated_token_account", "simulation": "required", "defaultMode": "dry_run"}, - "proofs": {"synthetic": ["canonical_00", "legacy_empty", "classic_token_program", "token_2022_program", "wrong_ata", "missing_account", "extra_account", "duplicate_account", "wrong_flags", "unknown_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": "not_tested", "mainnetSignatures": []} + "proofs": {"synthetic": ["canonical_00", "legacy_empty", "classic_token_program", "token2022_program", "wrong_ata", "missing_account", "extra_account", "duplicate_account", "wrong_flags", "unknown_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": "not_tested", "mainnetSignatures": []} }, { "name": "create_idempotent", @@ -109,10 +113,10 @@ "runtimeRules": ["creates when absent", "succeeds without recreating when an initialized compatible ATA already exists", "fails when an existing account has a different wallet owner, mint or account owner program"], "event": "spl_associated_token_account.create_idempotent", "authorizedProjections": ["token_accounts:ata_created_or_reused_idempotently"], - "forbiddenProjections": ["token_balance_snapshot", "duplicate_spl_token_initialize_account_cpi", "token_2022_extension_fact"], + "forbiddenProjections": ["token_balance_snapshot", "duplicate_spl_token_initialize_account_cpi", "token2022_extension_fact"], "officialBuilder": {"available": true, "function": "create_associated_token_account_idempotent", "canonicalWireOnly": true}, "executorSupport": {"status": "supported", "operationCode": "spl_associated_token_account.create_idempotent", "builder": "create_associated_token_account_idempotent", "simulation": "required", "defaultMode": "dry_run"}, - "proofs": {"synthetic": ["canonical_01", "absent_account", "compatible_existing_account", "conflicting_existing_owner", "conflicting_existing_mint", "conflicting_existing_program", "classic_token_program", "token_2022_program", "wrong_ata", "wrong_flags", "unexpected_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": ["5Vw4QFpMa8oJ8MsLrvDg4RFzxqUh27mTFRFzzwJFoA4uAry8rZQc6GP92aidzWugn3CeZ5NYNxDp7tZ6bh8XyN1P", "2H9VfhDySdXMteazm2P3s2fTttJBQzMJinQtKqsLtkjDg7zbFFgiWG81UxRQF4va3bbR2pUV4QGo2qErisR8CPbP", "3wWTkx45LoDR3UaU8VUfsWxwHuLFyJyhrnDrmijCa7pXPdmJKz3rQ1LdyDvb78dvNRiKqw5ee7HuZ6Gjj1Gpfv6q", "bMMjoHcwbaTvLXerdQ4kbGXGb7wydiTyvSEwwmoKKLQcRWWBzqGUMYHZztonNnER1iWZ7yKp9p3neeMhypX4QAJ", "4RZKA3KwEbSqgU8UnemTgvd3fBgJmoSK2nmaaTNP8nJGTVh6DrFwrHVZYCBvLFvhvzUdi9p1KRFe4hHqYt7JbVSG"], "mainnetSignatures": ["2F9RvuCkevfJN7ju252hAWoCE58wagCXCWHQF9Wsdtsxvp3HcuNJQFCwU7zGqe3z3b8pv3vPp4xY5EH7KLcaHQCY"], "realCorpusStatus": "controlled classic and Token-2022 CreateIdempotent creation then compatible-existing reuse confirmed, materialized once per signature and replayed idempotently; search-discovered Token-2022 outer transaction remains additional corpus"} + "proofs": {"synthetic": ["canonical_01", "absent_account", "compatible_existing_account", "conflicting_existing_owner", "conflicting_existing_mint", "conflicting_existing_program", "classic_token_program", "token2022_program", "wrong_ata", "wrong_flags", "unexpected_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": ["5Vw4QFpMa8oJ8MsLrvDg4RFzxqUh27mTFRFzzwJFoA4uAry8rZQc6GP92aidzWugn3CeZ5NYNxDp7tZ6bh8XyN1P", "2H9VfhDySdXMteazm2P3s2fTttJBQzMJinQtKqsLtkjDg7zbFFgiWG81UxRQF4va3bbR2pUV4QGo2qErisR8CPbP", "3wWTkx45LoDR3UaU8VUfsWxwHuLFyJyhrnDrmijCa7pXPdmJKz3rQ1LdyDvb78dvNRiKqw5ee7HuZ6Gjj1Gpfv6q", "bMMjoHcwbaTvLXerdQ4kbGXGb7wydiTyvSEwwmoKKLQcRWWBzqGUMYHZztonNnER1iWZ7yKp9p3neeMhypX4QAJ", "4RZKA3KwEbSqgU8UnemTgvd3fBgJmoSK2nmaaTNP8nJGTVh6DrFwrHVZYCBvLFvhvzUdi9p1KRFe4hHqYt7JbVSG"], "mainnetSignatures": ["2F9RvuCkevfJN7ju252hAWoCE58wagCXCWHQF9Wsdtsxvp3HcuNJQFCwU7zGqe3z3b8pv3vPp4xY5EH7KLcaHQCY"], "realCorpusStatus": "controlled classic and Token-2022 CreateIdempotent creation then compatible-existing reuse confirmed, materialized once per signature and replayed idempotently; search-discovered Token-2022 outer transaction remains additional corpus"} }, { "name": "recover_nested", @@ -134,16 +138,16 @@ "runtimeRules": ["all three derived addresses must match their observed accounts", "owner and nested token accounts must be initialized and coherent with their respective mints", "wallet owner must sign", "complete nested token balance is moved to the wallet destination ATA", "nested account is closed and its lamports are returned to the wallet"], "event": "spl_associated_token_account.recover_nested", "authorizedProjections": ["token_accounts:nested_ata_recovered", "risk:nested_ata_anti_pattern_recovered"], - "forbiddenProjections": ["duplicate_spl_token_transfer_cpi", "duplicate_spl_token_close_account_cpi", "token_balance_snapshot", "token_2022_extension_fact"], + "forbiddenProjections": ["duplicate_spl_token_transfer_cpi", "duplicate_spl_token_close_account_cpi", "token_balance_snapshot", "token2022_extension_fact"], "officialBuilder": {"available": true, "function": "recover_nested", "canonicalWireOnly": true}, "executorSupport": {"status": "supported", "operationCode": "spl_associated_token_account.recover_nested", "builder": "recover_nested", "simulation": "required", "defaultMode": "dry_run"}, - "proofs": {"synthetic": ["canonical_02", "classic_token_program", "token_2022_program", "valid_three_pda_relationships", "wrong_nested_ata", "wrong_destination_ata", "wrong_owner_ata", "owner_and_nested_mints_not_inverted", "missing_account", "extra_account", "duplicate_account", "wrong_flags", "unexpected_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": ["37LG6GdMRp5ECG8qf1RSYxmriJk75UtCwqwzXZWpArebkKo6BQvGhYEnbDh2A6KWiUaHK28Zy1gGGZ5zihvrHskM"], "mainnetSignatures": [], "realCorpusStatus": "controlled classic RecoverNested confirmed with positive raw balance transfer, nested ATA closure, owner and destination post-validation, two distinct ATA lifecycle and risk projections, and idempotent second replay", "controlledDevnetFixture": {"walletOwner": "DwuAapPLg6pEJ4QhmxvPg8rzkavmYdg5FW4dfEMcg8B2", "ownerMint": "So11111111111111111111111111111111111111112", "ownerAssociatedTokenAccount": "3tdXq1W7vEbbkxQmT1r2fc349uYti98zpwLKhp7FFbF5", "nestedMint": "3fd5CqP1w4Y1xeMoAe3apA7Jf5SbL3vboxv7ihyXhC9A", "nestedAssociatedTokenAccount": "AAyvGeKpq6i3kxMcScJLcN2u5iyAsspr731LhgXygti5", "walletNestedMintAssociatedTokenAccount": "69TP2QoSx2inueFAEb6npjumH5o3wGJQDSwwAJLLfyWp", "rawAmountTransferred": "1000000000", "nestedAccountClosed": true, "destinationUiBalanceAfter": "1", "materializedOutputCount": 2}} + "proofs": {"synthetic": ["canonical_02", "classic_token_program", "token2022_program", "valid_three_pda_relationships", "wrong_nested_ata", "wrong_destination_ata", "wrong_owner_ata", "owner_and_nested_mints_not_inverted", "missing_account", "extra_account", "duplicate_account", "wrong_flags", "unexpected_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": ["37LG6GdMRp5ECG8qf1RSYxmriJk75UtCwqwzXZWpArebkKo6BQvGhYEnbDh2A6KWiUaHK28Zy1gGGZ5zihvrHskM"], "mainnetSignatures": [], "realCorpusStatus": "controlled classic RecoverNested confirmed with positive raw balance transfer, nested ATA closure, owner and destination post-validation, two distinct ATA lifecycle and risk projections, and idempotent second replay", "controlledDevnetFixture": {"walletOwner": "DwuAapPLg6pEJ4QhmxvPg8rzkavmYdg5FW4dfEMcg8B2", "ownerMint": "So11111111111111111111111111111111111111112", "ownerAssociatedTokenAccount": "3tdXq1W7vEbbkxQmT1r2fc349uYti98zpwLKhp7FFbF5", "nestedMint": "3fd5CqP1w4Y1xeMoAe3apA7Jf5SbL3vboxv7ihyXhC9A", "nestedAssociatedTokenAccount": "AAyvGeKpq6i3kxMcScJLcN2u5iyAsspr731LhgXygti5", "walletNestedMintAssociatedTokenAccount": "69TP2QoSx2inueFAEb6npjumH5o3wGJQDSwwAJLLfyWp", "rawAmountTransferred": "1000000000", "nestedAccountClosed": true, "destinationUiBalanceAfter": "1", "materializedOutputCount": 2}} } ], "offlineCorpus": { "status": "implemented_and_operator_validated_in_decoder_unit_tests", "wire": ["create_00", "legacy_empty_create", "create_idempotent_01", "recover_nested_02", "unknown_tag", "rejected_suffix"], - "tokenPrograms": ["spl_token_classic", "token_2022"], + "tokenPrograms": ["spl_token_classic", "token2022"], "locations": ["outer", "inner_cpi"], "transactionOutcomes": ["committed", "failed_uncommitted_intent"], "accountShapes": ["canonical", "missing", "extra", "duplicate", "wrong_flags", "wrong_derived_address", "unsupported_token_program", "wrong_system_program"], @@ -155,7 +159,8 @@ "idempotenceIdentity": "signature + instruction_path + program_id + normalized_operation + ata", "projectionOwners": [ { - "crate": "kb_materializer_token_accounts", + "crate": "kb-lib", + "component": "materializer.token.accounts", "facts": [ "ata_created", "ata_created_or_reused_idempotently", @@ -164,7 +169,8 @@ "justification": "ATA creation and recovery are stable token-account lifecycle facts; this crate already owns instruction-level token-account mutations." }, { - "crate": "kb_materializer_risk", + "crate": "kb-lib", + "component": "materializer.risk", "facts": [ "nested_ata_anti_pattern_recovered" ], @@ -173,15 +179,18 @@ ], "explicitNoProjection": [ { - "crate": "kb_materializer_lifecycle", - "reason": "Native program lifecycle remains owned here; duplicating ATA lifecycle would overlap kb_materializer_token_accounts." + "crate": "kb-lib", + "component": "materializer.lifecycle", + "reason": "Native program lifecycle remains owned here; duplicating ATA lifecycle would overlap the token-account materializer." }, { - "crate": "kb_materializer_admin", + "crate": "kb-lib", + "component": "materializer.admin", "reason": "ATA instructions do not change a mint authority, freeze authority, close authority or multisig configuration." }, { - "crate": "kb_materializer_fees", + "crate": "kb-lib", + "component": "materializer.fees", "reason": "ATA wire does not prove an exact rent or network-fee amount; core balance changes and execution validation retain those facts." } ], @@ -195,7 +204,7 @@ "deploymentAudit": { "localnet": {"status": "not_tested", "evidence": []}, "devnet": {"status": "classic and Token-2022 CreateIdempotent creation and compatible-existing reuse confirmed; classic RecoverNested positive-balance recovery confirmed", "evidence": ["5Vw4QFpMa8oJ8MsLrvDg4RFzxqUh27mTFRFzzwJFoA4uAry8rZQc6GP92aidzWugn3CeZ5NYNxDp7tZ6bh8XyN1P", "2H9VfhDySdXMteazm2P3s2fTttJBQzMJinQtKqsLtkjDg7zbFFgiWG81UxRQF4va3bbR2pUV4QGo2qErisR8CPbP", "3wWTkx45LoDR3UaU8VUfsWxwHuLFyJyhrnDrmijCa7pXPdmJKz3rQ1LdyDvb78dvNRiKqw5ee7HuZ6Gjj1Gpfv6q", "bMMjoHcwbaTvLXerdQ4kbGXGb7wydiTyvSEwwmoKKLQcRWWBzqGUMYHZztonNnER1iWZ7yKp9p3neeMhypX4QAJ", "4RZKA3KwEbSqgU8UnemTgvd3fBgJmoSK2nmaaTNP8nJGTVh6DrFwrHVZYCBvLFvhvzUdi9p1KRFe4hHqYt7JbVSG", "37LG6GdMRp5ECG8qf1RSYxmriJk75UtCwqwzXZWpArebkKo6BQvGhYEnbDh2A6KWiUaHK28Zy1gGGZ5zihvrHskM"], "controlledToken2022Fixture": {"mint": "3DxKAUfCZkR9oRfMXeRNpiVL464eKbTieymBrVhsoKTE", "mintOwner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "mintBaseLength": 82, "walletOwner": "DwuAapPLg6pEJ4QhmxvPg8rzkavmYdg5FW4dfEMcg8B2", "associatedTokenAccount": "6WfCJPt7GZQyMJAUS1AMHJrD7Vid8e9xUEQVgi5Q9C9Y", "accountLength": 170, "accountExtension": "immutable_owner", "creationSlot": 476702448, "existingReuseSlot": 476703343}}, - "mainnet": {"status": "search_discovered_token_2022_create_idempotent_not_yet_replayed", "evidence": ["2F9RvuCkevfJN7ju252hAWoCE58wagCXCWHQF9Wsdtsxvp3HcuNJQFCwU7zGqe3z3b8pv3vPp4xY5EH7KLcaHQCY"]}, + "mainnet": {"status": "search_discovered_token2022_create_idempotent_not_yet_replayed", "evidence": ["2F9RvuCkevfJN7ju252hAWoCE58wagCXCWHQF9Wsdtsxvp3HcuNJQFCwU7zGqe3z3b8pv3vPp4xY5EH7KLcaHQCY"]}, "rateLimitRecovery": "preserve confirmed signatures and resume bounded hydration; never recreate accounts blindly after HTTP 429" }, "nonClaims": [ diff --git a/docs/SPL_MEMO_MATRIX.json b/docs/SPL_MEMO_MATRIX.json index 34a4b6b..1436b18 100644 --- a/docs/SPL_MEMO_MATRIX.json +++ b/docs/SPL_MEMO_MATRIX.json @@ -1,13 +1,14 @@ { "file": "docs/SPL_MEMO_MATRIX.json", - "version": 9, + "version": 10, "matrixVersion": 4, "scope": "SPL Memo v1, v3 et v4", "bot3Migration": { "decoderModule": "kb_lib::decoder::spl::memo", "publicDecoder": "kb_lib::SplMemoDecoder", "decoderStatus": "ported_in_0.1.0-pre.005", - "materializerStatus": "pending_later_tranche", + "publicMaterializer": "kb_lib::TransactionAnnotationMaterializer", + "materializerStatus": "ported_in_0.1.0-pre.011", "executorStatus": "pending_later_tranche" }, "interface": { @@ -113,7 +114,8 @@ "unknownProgramProducesObservation": false }, "materializationContract": { - "crate": "kb_materializer_transaction_annotations", + "crate": "kb-lib", + "component": "materializer.transaction.annotations", "processorName": "transaction_annotations", "materializedFamily": "transaction_annotation", "acceptedEntries": ["add_memo", "memo_intent", "invalid_memo_attempt"], diff --git a/docs/SPL_TOKEN_2022_CONFIDENTIAL_EXECUTION_AUDIT.md b/docs/SPL_TOKEN2022_CONFIDENTIAL_EXECUTION_AUDIT.md similarity index 99% rename from docs/SPL_TOKEN_2022_CONFIDENTIAL_EXECUTION_AUDIT.md rename to docs/SPL_TOKEN2022_CONFIDENTIAL_EXECUTION_AUDIT.md index f7670fa..125ae37 100644 --- a/docs/SPL_TOKEN_2022_CONFIDENTIAL_EXECUTION_AUDIT.md +++ b/docs/SPL_TOKEN2022_CONFIDENTIAL_EXECUTION_AUDIT.md @@ -1,4 +1,4 @@ - + # Audit d’exécution Confidential Transfer Token-2022 diff --git a/docs/SPL_TOKEN_2022_MATRIX.json b/docs/SPL_TOKEN2022_MATRIX.json similarity index 99% rename from docs/SPL_TOKEN_2022_MATRIX.json rename to docs/SPL_TOKEN2022_MATRIX.json index e492d21..ff28f44 100644 --- a/docs/SPL_TOKEN_2022_MATRIX.json +++ b/docs/SPL_TOKEN2022_MATRIX.json @@ -1,5 +1,5 @@ { - "file": "docs/SPL_TOKEN_2022_MATRIX.json", + "file": "docs/SPL_TOKEN2022_MATRIX.json", "version": "0.1.0-pre.008", "schemaVersion": 1, "matrixStatus": "exact_decoder_leaf_coverage_proven_pending_materialization_executor_preflight_and_cluster_corpus_completion", @@ -30,7 +30,7 @@ "default", "serde" ], - "leafConsumer": "kb-lib.decoder.spl.token_2022", + "leafConsumer": "kb-lib.decoder.spl.token2022", "operatorEvidence": "cargo tree -i spl-token-2022-interface -e features", "publishedCandidateAudited": "3.1.1", "publishedCandidateStatus": "matches_confirmed_workspace_resolution", @@ -2060,7 +2060,7 @@ "stable_fact_only_no_score" ], "lifecycle": [ - "no_token_2022_claim_until_non_overlap_is_proven" + "no_token2022_claim_until_non_overlap_is_proven" ] }, "forbiddenClaims": [ diff --git a/docs/SPL_TOKEN_2022_SOURCE_AUDIT.md b/docs/SPL_TOKEN2022_SOURCE_AUDIT.md similarity index 99% rename from docs/SPL_TOKEN_2022_SOURCE_AUDIT.md rename to docs/SPL_TOKEN2022_SOURCE_AUDIT.md index 00d2b2a..1127df3 100644 --- a/docs/SPL_TOKEN_2022_SOURCE_AUDIT.md +++ b/docs/SPL_TOKEN2022_SOURCE_AUDIT.md @@ -1,4 +1,4 @@ - + # Audit des sources Token-2022 résolues diff --git a/docs/SPL_TOKEN_2022_VALIDATION_MATRIX.json b/docs/SPL_TOKEN2022_VALIDATION_MATRIX.json similarity index 98% rename from docs/SPL_TOKEN_2022_VALIDATION_MATRIX.json rename to docs/SPL_TOKEN2022_VALIDATION_MATRIX.json index 8cedd27..2bea77b 100644 --- a/docs/SPL_TOKEN_2022_VALIDATION_MATRIX.json +++ b/docs/SPL_TOKEN2022_VALIDATION_MATRIX.json @@ -39,7 +39,7 @@ ] }, { - "id": "token_2022_public_devnet", + "id": "token2022_public_devnet", "environment": "devnet", "status": "not_run", "requiredEvidence": [ diff --git a/docs/TRACING_CONTRACT.md b/docs/TRACING_CONTRACT.md index e0fae05..006643a 100644 --- a/docs/TRACING_CONTRACT.md +++ b/docs/TRACING_CONTRACT.md @@ -1,5 +1,5 @@ - + # Contrat de tracing par crate et composant @@ -62,11 +62,14 @@ kb-lib.decoder.spl.associated_token_account kb-lib.decoder.spl.elgamal_registry kb-lib.decoder.spl.memo kb-lib.decoder.spl.token -kb-lib.decoder.spl.token_2022 +kb-lib.decoder.spl.token2022 kb-lib.materializer.admin kb-lib.materializer.compliance kb-lib.materializer.lifecycle +kb-lib.materializer.risk kb-lib.materializer.staking +kb-lib.materializer.token +kb-lib.materializer.transaction kb-logging kb-store ``` diff --git a/docs/legacy-khadhroony-bot2/CHANGELOG.md b/docs/legacy-khadhroony-bot2/CHANGELOG.md index b08dcc6..9414f72 100644 --- a/docs/legacy-khadhroony-bot2/CHANGELOG.md +++ b/docs/legacy-khadhroony-bot2/CHANGELOG.md @@ -35,7 +35,7 @@ Validation du jalon de cadrage stockage : conventions PostgreSQL définies autou ## 0.2.1 — contrats `kb_store_core` et replay instruction-level -Validation du jalon de contrats storage : `kb_store_core` expose les types communs backend-agnostiques pour pagination, healthcheck, migrations, erreurs de stockage, DTOs applicatifs, entities proches SQL et traits repositories sans implémentation PostgreSQL. Les contrats couvrent le raw RPC et WebSocket, le cycle de vie raw `Full` / `Compacted` / `Archived` / `Purged`, les états de traitement raw, la signature optionnelle des notifications WebSocket, la déduplication par `notification_key`, le lien futur optionnel notification vers transaction canonique, ainsi que le replay par instruction. Le replay est défini comme un scheduling au niveau instruction, mais le décodage reçoit un contexte extrait complet via `CoreInstructionReplayInput` : instruction ciblée, account keys, logs, balance changes et contexte transactionnel minimal. Les repositories restent abstraits et ne créent encore ni pool PostgreSQL, ni migration SQL réelle. Validation locale effectuée : `cargo test -p kb_store_core` avec 28 tests passés et `cargo clippy --all-targets` sans avertissement. Les validations précédentes du jalon ont également confirmé `kb_store_pg` sans test actif, `kb_config` avec 35 tests passés et `kb_app_demo` avec 28 tests passés. +Validation du jalon de contrats storage : `kb_store_core` expose les types communs backend-agnostiques pour pagination, healthcheck, migrations, erreurs de stockage, DTOs applicatifs, entities proches SQL et traits repositories sans implémentation PostgreSQL. Les contrats couvrent le raw RPC et WebSocket, le cycle de vie raw `Full` / `Compacted` / `Archived` / `Purged`, les états de traitement raw, la signature optionnelle des notifications WebSocket, la déduplication par `notification_key`, le lien futur optionnel notification vers transaction canonique, ainsi que le replay par instruction. Le replay est défini comme un scheduling au niveau instruction, mais le décodage reçoit un contexte extrait complet via `MdCoreInstructionReplayInput` : instruction ciblée, account keys, logs, balance changes et contexte transactionnel minimal. Les repositories restent abstraits et ne créent encore ni pool PostgreSQL, ni migration SQL réelle. Validation locale effectuée : `cargo test -p kb_store_core` avec 28 tests passés et `cargo clippy --all-targets` sans avertissement. Les validations précédentes du jalon ont également confirmé `kb_store_pg` sans test actif, `kb_config` avec 35 tests passés et `kb_app_demo` avec 28 tests passés. ## 0.2.2 — infrastructure PostgreSQL minimale @@ -47,7 +47,7 @@ Validation du jalon raw store minimal : `kb_store_pg` crée et initialise les de ## 0.2.4 — core Solana normalisé minimal -Validation du jalon core store minimal : `kb_store_pg` crée et initialise maintenant les tables core `kb_sol_core_transactions`, `kb_sol_core_account_keys`, `kb_sol_core_instructions`, `kb_sol_core_inner_instructions`, `kb_sol_core_logs` et `kb_sol_core_balance_changes`, en complément du raw store `0.2.3`, sans schema PostgreSQL applicatif explicite. Les migrations et l'initializer utilisent des noms SQL préfixés et explicites pour les contraintes et index : `pk_`, `fk_`, `ck_`, `ux_` et `ix_`. L'initialisation raw/core est sérialisée par un verrou PostgreSQL `pg_advisory_xact_lock` afin d'éviter les courses concurrentes pendant les tests ou les démarrages parallèles. `CoreTransactionStore` dispose de l'implémentation PostgreSQL minimale pour insérer les transactions core, account keys, instructions, inner instructions, logs et deltas de balances, puis reconstruire `CoreInstructionReplayInput` pour les futurs décodeurs. Le script de maintenance `kb_store_pg/maintenance/drop_raw_core_store.sql` permet de réinitialiser explicitement les tables raw/core locales dans l'ordre inverse des dépendances. Validation locale effectuée : `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana cargo test -p kb_store_pg -- --nocapture` avec 30 tests passés, création vérifiée des 8 tables dans PostgreSQL, réinitialisation validée via le script de maintenance, puis `cargo clippy --all-targets` sans avertissement. Le worker d'extraction raw RPC vers core, les observations et le ledger ops sont conservés pour les jalons suivants. +Validation du jalon core store minimal : `kb_store_pg` crée et initialise maintenant les tables core `kb_sol_core_transactions`, `kb_sol_core_account_keys`, `kb_sol_core_instructions`, `kb_sol_core_inner_instructions`, `kb_sol_core_logs` et `kb_sol_core_balance_changes`, en complément du raw store `0.2.3`, sans schema PostgreSQL applicatif explicite. Les migrations et l'initializer utilisent des noms SQL préfixés et explicites pour les contraintes et index : `pk_`, `fk_`, `ck_`, `ux_` et `ix_`. L'initialisation raw/core est sérialisée par un verrou PostgreSQL `pg_advisory_xact_lock` afin d'éviter les courses concurrentes pendant les tests ou les démarrages parallèles. `CoreTransactionStore` dispose de l'implémentation PostgreSQL minimale pour insérer les transactions core, account keys, instructions, inner instructions, logs et deltas de balances, puis reconstruire `MdCoreInstructionReplayInput` pour les futurs décodeurs. Le script de maintenance `kb_store_pg/maintenance/drop_raw_core_store.sql` permet de réinitialiser explicitement les tables raw/core locales dans l'ordre inverse des dépendances. Validation locale effectuée : `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana cargo test -p kb_store_pg -- --nocapture` avec 30 tests passés, création vérifiée des 8 tables dans PostgreSQL, réinitialisation validée via le script de maintenance, puis `cargo clippy --all-targets` sans avertissement. Le worker d'extraction raw RPC vers core, les observations et le ledger ops sont conservés pour les jalons suivants. ## 0.2.5 — diagnostics SQL PostgreSQL dans `kb_app_demo` diff --git a/docs/legacy-khadhroony-bot2/ROADMAP.md b/docs/legacy-khadhroony-bot2/ROADMAP.md index f21cd46..a49aa0b 100644 --- a/docs/legacy-khadhroony-bot2/ROADMAP.md +++ b/docs/legacy-khadhroony-bot2/ROADMAP.md @@ -172,7 +172,7 @@ Ce fichier contient les changements futurs et le phasage prévu. Il ne remplace - [x] Ajouter les types communs : pagination, tri, limites, healthcheck, statut migration. - [x] Ajouter les premiers DTO génériques : raw RPC transaction, raw WS notification, core transaction, core instruction. - [x] Ajouter les contrats core pour account keys, logs et balance changes extraits. -- [x] Ajouter `CoreInstructionReplayInput` pour fournir aux décodeurs une instruction avec contexte extrait. +- [x] Ajouter `MdCoreInstructionReplayInput` pour fournir aux décodeurs une instruction avec contexte extrait. - [x] Ajouter les contrats de cycle de vie raw : état de rétention, état de traitement et mark lifecycle. - [x] Ajouter les contrats de replay par instruction : état instruction, filtre de replay et lifecycle mark. - [x] Ajouter les premiers traits repository sans implémentation SQL. @@ -229,7 +229,7 @@ Ce fichier contient les changements futurs et le phasage prévu. Il ne remplace ### 0.2.4 — core Solana normalisé minimal - [x] Créer les tables core minimales : `kb_sol_core_transactions`, `kb_sol_core_account_keys`, `kb_sol_core_instructions`, `kb_sol_core_inner_instructions`, `kb_sol_core_logs`, `kb_sol_core_balance_changes`. -- [x] Construire `CoreInstructionReplayInput` depuis les tables `core` pour les décodeurs. +- [x] Construire `MdCoreInstructionReplayInput` depuis les tables `core` pour les décodeurs. - [x] Marquer les instructions insérées comme `Pending` pour permettre un replay instruction-level. - [x] Préparer le replay partiel par état, slot et program id via `CoreInstructionReplayFilter`. - [x] Ajouter une initialisation idempotente raw/core via `PostgresStore::initialize_store_schema()`. @@ -460,7 +460,7 @@ Les contrôles autrefois prévus dans `0.3.5` sont reclassés ainsi : la stabili - [x] Auditer les crates utilisant `tracing.workspace = true` et couvrir les treize crates alors actives par un test de constante canonique et par les routes des trois profils. - [x] Ajouter le tracing propriétaire manquant sur les clients/pools HTTP et WebSocket ainsi que sur le backfill ; promouvoir les inputs decode unmatched, statuts failed/unsupported et échecs de matérialisation/persistance au niveau `error`. - [x] Formaliser dans `docs/SOLANA_INTERFACE_DEPENDENCIES.md` la politique d’interfaces officielles : dépendance seulement au point de consommation, priorité `wincode` puis Borsh, parser borné lorsque l’interface n’expose que `bincode`. -- [x] Passer `CoreInstructionReplayInput` au contrat `2` avec une liste stable et numériquement ordonnée des instructions outer, sans migration SQL, afin de résoudre les références inter-instructions des précompiles. +- [x] Passer `MdCoreInstructionReplayInput` au contrat `2` avec une liste stable et numériquement ordonnée des instructions outer, sans migration SQL, afin de résoudre les références inter-instructions des précompiles. - [x] Décoder `zk_elgamal_proof` dans `pre.015` selon `solana-zk-elgamal-proof-interface ^0.1` et le runtime Agave : treize discriminants, preuves inline ou référencées par compte, contexte optionnel et fermeture du contexte, sans recalcul cryptographique. - [x] Décoder dans `pre.016` l’ancien `zk_token_proof` comme compatibilité historique, puis retirer dans `pre.019` la dépendance dépréciée `solana-zk-token-sdk` au profit d’un miroir wire local borné des dix-sept discriminants et tailles auditées. - [x] Décoder les loaders `native_loader`, `bpf_loader_deprecated`, `bpf_loader`, `bpf_loader_upgradeable` et `loader_v4` ; classer l’invocation Native Loader opaque comme `ignored` sans sémantique inventée. @@ -532,14 +532,14 @@ Les contrôles autrefois prévus dans `0.3.5` sont reclassés ainsi : la stabili #### Suite d’orchestration -- [x] `pre.004` : ajouter dans `kb_rpc` les adaptateurs typés `getGenesisHash`, `getLatestBlockhash`, `getFeeForMessage` et `simulateTransaction`, avec routage par rôle, classification des clusters publics, diagnostics runtime et conversion vers `ExecutionSimulationResult`, sans signature ni envoi. +- [x] `pre.004` : ajouter dans `kb_rpc` les adaptateurs typés `getGenesisHash`, `getLatestBlockhash`, `getFeeForMessage` et `simulateTransaction`, avec routage par rôle, classification des clusters publics, diagnostics runtime et conversion vers `ExApiExecutionSimulationResult`, sans signature ni envoi. - [x] `pre.004` : documenter dans `kb_executor_solana_core/README.md` chaque fonction publique, les six opérations constructibles, leurs paramètres, résultats, effets et frontières. - [x] Valider localement `pre.004` : `kb_rpc` 63 tests, `kb_execution_api` 21 tests, `kb_execution_safety` 13 tests, `kb_executor_solana_core` 10 tests, `kb_config` 40 tests et Clippy global propre. - [x] `pre.005` : ajouter `kb_execution_solana` pour assembler les instructions planifiées en transaction legacy, produire les payloads base64 de frais/simulation, lier la simulation au hash exact du message, résoudre exactement les signataires requis via l’interface Solana `Signer` et signer séparément hors Tauri. - [x] `pre.005` : renommer la constante interne en `MAINNET_GENESIS_HASH` sans changer sa valeur ; conserver `mainnet-beta` seulement comme alias historique des endpoints/CLI et renommer le variant public en `Mainnet` sérialisé `mainnet`. - [x] `pre.005` : distinguer la simulation exacte de la simulation avec remplacement de blockhash et interdire qu’un résultat `replaceRecentBlockhash=true` autorise la signature du message original. - [x] Valider localement les tests ciblés de `pre.005`/`pre.006` : `kb_execution_solana` 7 tests, `kb_execution_api` 22 tests, `kb_execution_safety` 15 tests, `kb_rpc` 63 tests, `kb_executor_solana_core` 10 tests, `kb_wallet` 6 tests et `kb_config` 40 tests. -- [x] `pre.006` : corriger la compilation croisée de `pre.005`, supprimer l’avertissement TS-rs sur l’alias historique `mainnet_beta`, utiliser le trait public `TypedInstructionExecutor` dans les tests d’assemblage, resynchroniser le contrat de simulation RPC et rendre les erreurs de routage tracing explicites. +- [x] `pre.006` : corriger la compilation croisée de `pre.005`, supprimer l’avertissement TS-rs sur l’alias historique `mainnet_beta`, utiliser le trait public `ExApiTypedInstructionExecutor` dans les tests d’assemblage, resynchroniser le contrat de simulation RPC et rendre les erreurs de routage tracing explicites. - [x] `pre.007` : supprimer le dernier opérateur `?` introduit dans un chemin de production de `kb_execution_api`, le remplacer par un `match` avec propagation explicite et auditer les fichiers d’exécution `0.4.2` contre `?`, `unwrap` et `expect` de production. - [x] Valider localement `pre.007` : `kb_execution_api` 22 tests et Clippy global propre. - [x] `pre.008` : ajouter les contrats RPC typés `getBalance`, `requestAirdrop`, `sendTransaction`, `getSignatureStatuses` et `getBlockHeight`, avec routage par rôle, préflight obligatoire, contrôle de la signature retournée et confirmation bornée jusqu’à succès, échec, expiration ou timeout. @@ -603,7 +603,7 @@ Les contrôles autrefois prévus dans `0.3.5` sont reclassés ainsi : la stabili - [x] Valider localement `pre.019` : `kb_executor_solana_core` 70 tests, `kb_execution_api` 22, `kb_execution_safety` 15, `kb_execution_solana` 12, `kb_rpc` 70 et Clippy global propre. - [x] `pre.020` : onze opérations Loader v3 et neuf opérations Loader v4 réellement constructibles, avec déploiement/upgrade/autorités/fermeture hors UI; BPF Loader v1/v2 restent historiques `decode-only` et Native Loader est classé sans instruction client. - [x] Valider localement `pre.020` : `kb_executor_solana_core` 81 tests, `kb_decoder_solana_core` 115, `kb_execution_api` 22, `kb_execution_safety` 15, `kb_execution_solana` 12 et `kb_rpc` 70. -- [x] `pre.021` : centraliser dans un module privé les parsers `Pubkey`/program ID et les validations communes de longueur, montant positif, comptes distincts, dérivation seedée et erreurs partagées ; supprimer les implémentations de production identiques sans modifier les 109 opérations ni leur wire. +- [x] `pre.021` : centraliser dans un module privé les parsers `MdPubkey`/program ID et les validations communes de longueur, montant positif, comptes distincts, dérivation seedée et erreurs partagées ; supprimer les implémentations de production identiques sans modifier les 109 opérations ni leur wire. - [x] Valider localement `pre.021` après `fix.001` : `kb_executor_solana_core` 86 tests et `cargo clippy --all-targets` propre ; ce Clippy couvre également les changements Loader de `pre.020`. - [x] `pre.022` : implémenter le préflight stateful Localnet/Devnet pour ALT, Config, Feature, Slashing et contextes ZK ElGamal ; ajouter `getEpochInfo` typé et la matrice machine-readable complète des 18 surfaces natives avec classification de toute opération non invocable. - [x] Valider localement `pre.022` : `kb_executor_solana_core` 87 tests, `kb_pipeline` 56 tests, `kb_rpc` 71 tests, `kb_execution_api` 22 tests, `kb_execution_safety` 15 tests, `kb_execution_solana` 12 tests, validateur de matrice réussi et `cargo clippy --all-targets` propre. diff --git a/docs/legacy-khadhroony-bot2/RULES.md b/docs/legacy-khadhroony-bot2/RULES.md index e0aeec2..245e53a 100644 --- a/docs/legacy-khadhroony-bot2/RULES.md +++ b/docs/legacy-khadhroony-bot2/RULES.md @@ -138,7 +138,7 @@ Aucun renommage massif de crates n'est autorisé sans étape de contrôle dédi - Une crate est opérationnelle lorsqu’elle effectue des I/O, orchestre un pipeline, décode, matérialise, exécute, applique une politique runtime ou prend une décision mutable observable. - Toute crate opérationnelle ajoutée ou modifiée doit dépendre de `tracing` depuis le workspace et déclarer exactement un `pub(crate) const TRACING_TARGET` dans `src/constants.rs`. -- La valeur canonique de `TRACING_TARGET` est le nom exact du package Cargo. Les targets historiques `khbot.*`, les suffixes de module et les targets de fenêtre sont interdits dans les nouvelles modifications. +- La valeur canonique de `DC_METADATA_MTM_TRACING_TARGET` est le nom exact du package Cargo. Les targets historiques `khbot.*`, les suffixes de module et les targets de fenêtre sont interdits dans les nouvelles modifications. - Les macros `tracing` doivent utiliser `target: crate::TRACING_TARGET` et des champs structurés stables. La granularité interne passe par `action`, `stage`, `window`, `campaign_id`, `signature`, `instruction_path`, `program_id`, `processor_name`, `processor_version`, `status` et `error_code`. - Les crates passives de types, contrats, DTO, API sans exécution, registres ou constantes restent sans dépendance `tracing`. `kb_config` reste une exception de bootstrap tant que sa validation précède l’installation du subscriber. - Il est interdit d’ajouter `tracing` sans événement réel ou de conserver un faux target uniquement consommé par `let _target`. @@ -150,14 +150,14 @@ Aucun renommage massif de crates n'est autorisé sans étape de contrôle dédi - Chaque profil doit router les événements vers les sorties globales `debug.log`, `info.log`, `error.jsonl` et `app.log`, puis vers `debug.log`, `info.log` et `error.jsonl` dans un répertoire propre à chaque crate utilisant `tracing`. - L’ajout ou la suppression de `tracing.workspace = true` dans une crate impose la mise à jour simultanée de la matrice de routes, de ses tests et de `docs/TRACING_CONTRACT.md`. - Le contrat détaillé est défini dans `docs/TRACING_CONTRACT.md`. -- L’audit mécanique spécifique au projet est exécuté par `python3 scripts/audit_khadhroony_workspace_rules.py`. Il couvre notamment `TRACING_TARGET` et l’usage obligatoire de `solana_pubkey::Pubkey` à la place de `solana_address::Address`. +- L’audit mécanique spécifique au projet est exécuté par `python3 scripts/audit_khadhroony_workspace_rules.py`. Il couvre notamment `DC_METADATA_MTM_TRACING_TARGET` et l’usage obligatoire de `solana_pubkey::Pubkey` à la place de `solana_address::Address`. ## Règles de réutilisation des interfaces Solana et SPL - Les dépendances déclarées dans `[workspace.dependencies]` forment un catalogue de versions et de features autorisées ; elles ne doivent être ajoutées à une crate consommatrice que lorsqu’un type, un encodeur, un décodeur ou un identifiant officiel est réellement utilisé. - Dans un `Cargo.toml`, placer dans `[dependencies]` toute crate référencée par le code de bibliothèque compilé en production. Réserver `[dev-dependencies]` aux références contenues exclusivement dans `#[cfg(test)]`, les tests d’intégration, benches ou exemples. Une dépendance de test vers un décodeur ou matérialiseur concret est légitime lorsqu’elle sert uniquement à éprouver une orchestration générique fondée sur les traits API ; elle ne prouve pas qu’une capacité de production manque. Toute promotion de `dev-dependencies` vers `dependencies` doit être motivée par un appel runtime réel, et toute dépendance runtime inutilisée doit être supprimée. -- Les registres de composition runtime des applications doivent énumérer explicitement chaque décodeur et matérialiseur concret activé. Toute nouvelle surface instructionnelle dotée d’un `EventMaterializer` doit être ajoutée au registre applicatif et couverte par un test d’inventaire ordonné ; une crate présente dans le workspace ou dans `kb_pipeline` n’est pas activée automatiquement. Les matérialiseurs exclusivement stateful qui n’implémentent pas `EventMaterializer` restent routés par leurs APIs de snapshots dédiées. +- Les registres de composition runtime des applications doivent énumérer explicitement chaque décodeur et matérialiseur concret activé. Toute nouvelle surface instructionnelle dotée d’un `MtApiEventMaterializer` doit être ajoutée au registre applicatif et couverte par un test d’inventaire ordonné ; une crate présente dans le workspace ou dans `kb_pipeline` n’est pas activée automatiquement. Les matérialiseurs exclusivement stateful qui n’implémentent pas `MtApiEventMaterializer` restent routés par leurs APIs de snapshots dédiées. - Les corrélations instruction/état doivent produire une issue explicite (`confirmed`, `contradicted` ou `not_applicable`) et ne doivent jamais transformer automatiquement une configuration observée en violation, score ou conclusion métier. - Une interface officielle Solana ou SPL étroite doit être préférée à `solana-sdk` lorsque son contrat suffit. - L’ordre de préférence des formats est : schéma officiel `wincode`, schéma officiel Borsh, puis parseur local borné reproduisant exactement le runtime lorsque l’interface officielle n’expose que `bincode`. diff --git a/kb-core/src/lib.rs b/kb-core/src/lib.rs index 84fddc9..6c42af2 100644 --- a/kb-core/src/lib.rs +++ b/kb-core/src/lib.rs @@ -10,12 +10,12 @@ mod error; mod module; /// Workspace-wide explicit error type. -pub use crate::error::Error; +pub use self::error::Error; /// Workspace-wide result alias. -pub use crate::error::Result; +pub use self::error::Result; /// Processing module category. -pub use crate::module::ModuleKind; +pub use self::module::ModuleKind; /// Stable module name. -pub use crate::module::ModuleName; +pub use self::module::ModuleName; /// Stable semantic module version. -pub use crate::module::ModuleVersion; +pub use self::module::ModuleVersion; diff --git a/kb-lib/README.md b/kb-lib/README.md index c34730b..57b1064 100644 --- a/kb-lib/README.md +++ b/kb-lib/README.md @@ -7,7 +7,7 @@ ## Décodeur Solana Core -`SolanaCoreDecoder` est le premier décodeur concret porté depuis bot2. Il implémente `InstructionDecoder` et `ProtocolDecoder` sans dépendre de PostgreSQL, du RPC, de Tauri ou du wallet. +`DcSolanaCoreDecoder` est le premier décodeur concret porté depuis bot2. Il implémente `DcApiInstructionDecoder` et `DcApiProtocolDecoder` sans dépendre de PostgreSQL, du RPC, de Tauri ou du wallet. Il couvre les 18 surfaces natives suivantes : @@ -25,13 +25,13 @@ La matrice `docs/NATIVE_SOLANA_DECODER_MATRIX.json` reste la source machine-read ## Décodeur SPL Memo -`SplMemoDecoder` couvre exactement les générations v1, v3 et v4. Le payload est lu comme un message brut sans discriminator, borné à 4 096 octets, puis projeté avec son texte UTF-8 complet, sa longueur, son SHA-256, les comptes ordonnés et le statut de commit. +`DcSplMemoDecoder` couvre exactement les générations v1, v3 et v4. Le payload est lu comme un message brut sans discriminator, borné à 4 096 octets, puis projeté avec son texte UTF-8 complet, sa longueur, son SHA-256, les comptes ordonnés et le statut de commit. Memo v1 ignore les comptes lors de la validation runtime. Memo v3 et v4 exigent que chaque compte fourni soit signer. Les transactions échouées restent des intentions non commitées et les payloads UTF-8 invalides ou signatures manquantes deviennent des tentatives invalides explicites. La matrice normative est `docs/SPL_MEMO_MATRIX.json`. ## Décodeur SPL Token classique -`SplTokenDecoder` couvre exclusivement le Program ID classique +`DcSplTokenDecoder` couvre exclusivement le Program ID classique `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`. Il publie 28 déclarations de couverture pour les tags `0..24`, `38`, `45` et `255`, y compris les variantes historiques, checked, `WithdrawExcessLamports`, `UnwrapLamports` et `Batch`. @@ -45,7 +45,7 @@ normative est `docs/SPL_TOKEN_MATRIX.json`. ## Décodeur SPL Associated Token Account -`SplAssociatedTokenAccountDecoder` couvre exclusivement +`DcSplAssociatedTokenAccountDecoder` couvre exclusivement `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`. Il reconnaît les trois variantes publiées `Create`, `CreateIdempotent` et `RecoverNested`, ainsi que l’encodage historique vide de `Create`. @@ -58,7 +58,7 @@ Program ID sans reconstruire leur état ni interpréter leurs extensions. La mat ## Décodeur SPL Token‑2022 -`SplToken2022Decoder` couvre exclusivement +`DcSplToken2022Decoder` couvre exclusivement `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. Il conserve les 48 enveloppes de premier niveau, les sous-instructions d’extensions dont le wire est officiellement identifiable, les interfaces Token Metadata et Token Group exécutées directement par Token‑2022, ainsi que `Batch` sans batch @@ -67,22 +67,22 @@ imbriqué. Le décodeur borne les payloads, les chaînes de metadata, le nombre d’enfants et les comptes cumulés. Les comptes, autorités, offsets de preuve, suffixes et chemins outer/inner restent ordonnés et exacts. Une transaction échouée produit une intention non commitée. Le parseur public -`parse_token_2022_state()` distingue Mint, Account et Multisig, conserve la base exacte et expose +`decoder_spl_token2022_parse_token2022_state()` distingue Mint, Account et Multisig, conserve la base exacte et expose les entrées TLV ordonnées sans inventer l’état d’un programme externe pointé. La matrice normative est `docs/SPL_TOKEN_2022_MATRIX.json`. ## Décodeur du registre ElGamal -`SplElgamalRegistryDecoder` couvre le programme indépendant +`DcSplElgamalRegistryDecoder` couvre le programme indépendant `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg`. Il décode exactement `CreateRegistry` et `UpdateRegistry`, conserve l’offset relatif de preuve et ne prétend jamais vérifier la preuve ZK. -`parse_elgamal_registry_state()` exige exactement 64 octets et restitue le wallet propriétaire, la +`decoder_spl_elgamal_registry_parse_elgamal_registry_state()` exige exactement 64 octets et restitue le wallet propriétaire, la clé publique ElGamal et le wire complet. La matrice normative est `docs/SPL_ELGAMAL_REGISTRY_MATRIX.json`. ## Décodeur Metaplex Token Metadata -`MetadataMetaplexTokenMetadataDecoder` couvre exclusivement +`DcMetadataMetaplexTokenMetadataDecoder` couvre exclusivement `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`. Il inventorie exactement les 58 discriminateurs `0..=57`, conserve les arguments Borsh, les comptes positionnels, les placeholders optionnels, les chemins outer/CPI et les transactions échouées @@ -100,22 +100,22 @@ politique d’exécution définitivement interdite. La matrice normative est ## API publique utile -- `EventMaterializer`, `MaterializerIdentity`, `MaterializationTransactionPolicy`, `MaterializerExecutionResult` et `MaterializedOutput` : contrat complet utilisable par un matérialiseur interne ou externe ; -- `LifecycleMaterializer`, `AdminMaterializer`, `ComplianceAuditMaterializer` et `StakingMaterializer` : matérialisateurs Solana natifs concrets ; -- `materialize_token_2022_admin_state_snapshots()` et `materialize_elgamal_registry_state_snapshot()` : projections stateful d’administration déjà exposées ; -- `SolanaCoreDecoder` : décodeur concret natif ; -- `SplMemoDecoder` : décodeur exact des trois générations SPL Memo ; -- `SplTokenDecoder` : décodeur exact du programme SPL Token classique ; -- `SplAssociatedTokenAccountDecoder` : décodeur exact du programme Associated Token Account ; -- `SplToken2022Decoder` : décodeur exact des instructions Token‑2022 ; -- `Token2022State`, `Token2022StateKind`, `Token2022TlvEntry` et `parse_token_2022_state()` : API publique de lecture d’état Token‑2022 ; -- `SplElgamalRegistryDecoder`, `ElGamalRegistryState` et `parse_elgamal_registry_state()` : API publique du registre ElGamal ; -- `MetadataMetaplexTokenMetadataDecoder` : décodeur exact du programme Metaplex Token Metadata ; +- `MtApiEventMaterializer`, `MtApiMaterializerIdentity`, `MtApiMaterializationTransactionPolicy`, `MtApiMaterializerExecutionResult` et `MtApiMaterializedOutput` : contrat complet utilisable par un matérialiseur interne ou externe ; +- `MtLifecycleMaterializer`, `MtAdminMaterializer`, `MtComplianceAuditMaterializer` et `MtStakingMaterializer` : matérialisateurs Solana natifs concrets ; +- `materialize_token2022_admin_state_snapshots()` et `materialize_elgamal_registry_state_snapshot()` : projections stateful d’administration déjà exposées ; +- `DcSolanaCoreDecoder` : décodeur concret natif ; +- `DcSplMemoDecoder` : décodeur exact des trois générations SPL Memo ; +- `DcSplTokenDecoder` : décodeur exact du programme SPL Token classique ; +- `DcSplAssociatedTokenAccountDecoder` : décodeur exact du programme Associated Token Account ; +- `DcSplToken2022Decoder` : décodeur exact des instructions Token‑2022 ; +- `DcToken2022State`, `DcToken2022StateKind`, `DcToken2022TlvEntry` et `decoder_spl_token2022_token2022_state()` : API publique de lecture d’état Token‑2022 ; +- `DcSplElgamalRegistryDecoder`, `DcSplElGamalRegistryState` et `decoder_spl_elgamal_registry_parse_elgamal_registry_state()` : API publique du registre ElGamal ; +- `DcMetadataMetaplexTokenMetadataDecoder` : décodeur exact du programme Metaplex Token Metadata ; - `kb_lib::decoder::metadata::metaplex_token_metadata` : parseurs et snapshots publics des comptes Metaplex ; -- `InstructionDecoder` : contrat de reconnaissance, couverture et décodage contextualisé ; -- `ProtocolDecoder` : contrat de compatibilité avec les observations historiques ; -- `CoreInstructionReplayInput` : input source-neutral produit par l’extraction core ; -- `DecoderExecutionResult`, `DecoderRecognition` et `DecoderCoverageDeclaration` : résultats typés du pipeline ; +- `DcApiInstructionDecoder` : contrat de reconnaissance, couverture et décodage contextualisé ; +- `DcApiProtocolDecoder` : contrat de compatibilité avec les observations historiques ; +- `MdCoreInstructionReplayInput` : input source-neutral produit par l’extraction core ; +- `DcApiDecoderExecutionResult`, `DcApiDecoderRecognition` et `DcApiDecoderCoverageDeclaration` : résultats typés du pipeline ; - modèles canoniques et nomenclature réexportés depuis la façade. Les helpers, constantes wire et types intermédiaires de chaque composant restent internes. Leurs noms sont préfixés au niveau de la façade interne afin d’éviter les collisions lors de la fusion des anciens crates. diff --git a/kb-lib/src/decoder.rs b/kb-lib/src/decoder.rs index f1d889a..cede0e6 100644 --- a/kb-lib/src/decoder.rs +++ b/kb-lib/src/decoder.rs @@ -3,164 +3,498 @@ //! Consolidated decoder modules. -pub mod adapter; -pub mod admin; -pub mod amm; -pub mod anchor; -pub mod api; -pub mod bridge; -pub mod clmm; -pub mod cpmm; -pub mod dlmm; -pub mod fees; -pub mod governance; -pub mod launchpad; -pub mod lending; -pub mod lock; -pub mod metadata; -pub mod nft; -pub mod orderbook; -pub mod perpetuals; -pub mod router; -pub mod rwa; -pub mod solana; -pub mod spl; -pub mod stable; -pub mod staking; -pub mod treasury; -pub mod vault; -pub mod vesting; -pub mod wallet; -pub mod weighted; +mod adapter; +mod admin; +mod amm; +mod anchor; +mod api; +mod bridge; +mod clmm; +mod cpmm; +mod dlmm; +mod fees; +mod governance; +mod launchpad; +mod lending; +mod lock; +mod metadata; +mod nft; +mod orderbook; +mod perpetuals; +mod router; +mod rwa; +mod solana; +mod spl; +mod stable; +mod staking; +mod treasury; +mod vault; +mod vesting; +mod wallet; +mod weighted; -/// One parsed SPL ElGamal registry instruction. -pub(crate) use self::spl::ParsedRegistryInstruction; +/// 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; +/// Bubblegum Set Collection Size discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR; +/// Burn discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_BURN_DISCRIMINATOR; +/// Historical Burn Edition NFT discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR; +/// Historical Burn NFT discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR; +/// Close Accounts discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR; +/// Close Escrow Account discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR; +/// Collect discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_COLLECT_DISCRIMINATOR; +/// Convert Master Edition V1 to V2 discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR; +/// Modern Create discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CREATE_DISCRIMINATOR; +/// Create Escrow Account discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR; +/// Historical Create Master Edition discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR; +/// Create Master Edition V3 discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR; +/// Historical Create Metadata Account discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR; +/// Historical Create Metadata Account V2 discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +/// Create Metadata Account V3 discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR; +/// Delegate discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_DELEGATE_DISCRIMINATOR; +/// Deprecated Create Master Edition discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR; +/// Deprecated Create Reservation List discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR; +/// Deprecated printing-token mint-new-edition discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR; +/// Deprecated Mint Printing Tokens discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR; +/// Deprecated Mint Printing Tokens Via Token discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR; +/// Deprecated Set Reservation List discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR; +/// Number of bytes retained in malformed-wire diagnostics. +pub(crate) use self::metadata::DC_METADATA_MTM_DIAGNOSTIC_PREFIX_BYTES; +/// Stable event payload contract version. +pub(crate) use self::metadata::DC_METADATA_MTM_EVENT_VERSION; +/// Freeze Delegated Account discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR; +/// Current pre-release instruction inventory. +pub(crate) use self::metadata::DC_METADATA_MTM_INSTRUCTION_ENTRIES; +/// Lock discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_LOCK_DISCRIMINATOR; +/// Maximum encoded base64 instruction payload size. +pub(crate) use self::metadata::DC_METADATA_MTM_MAX_BASE64_BYTES; +/// Maximum number of instruction accounts accepted by this decoder. +pub(crate) use self::metadata::DC_METADATA_MTM_MAX_INSTRUCTION_ACCOUNTS; +/// Tracing target for this decoder. +/// Maximum retained instruction payload size. +pub(crate) use self::metadata::DC_METADATA_MTM_MAX_INSTRUCTION_BYTES; +/// Migrate discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_MIGRATE_DISCRIMINATOR; +/// Modern Mint discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_MINT_DISCRIMINATOR; +/// Mint New Edition From Master Edition Via Token discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR; +/// Mint New Edition From Master Edition Via Vault Proxy discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR; +/// Modern Print discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_PRINT_DISCRIMINATOR; +/// Puff Metadata discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR; +/// Remove Creator Verification discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR; +/// Resize discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_RESIZE_DISCRIMINATOR; +/// Revoke Collection Authority discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR; +/// Revoke discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_REVOKE_DISCRIMINATOR; +/// Revoke Use Authority discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR; +/// Set And Verify Collection discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR; +/// Set And Verify Sized Collection Item discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +/// Set Collection Size discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR; +/// Set Token Standard discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR; +/// Sign Metadata discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR; +/// Stable decoder surface code. +pub(crate) use self::metadata::DC_METADATA_MTM_SURFACE_CODE; +/// Thaw Delegated Account discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR; +/// Canonical tracing target for this crate. +pub(crate) use self::metadata::DC_METADATA_MTM_TRACING_TARGET; +/// Transfer discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_TRANSFER_DISCRIMINATOR; +/// Transfer Out Of Escrow discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR; +/// Unlock discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UNLOCK_DISCRIMINATOR; +/// Unverify Collection discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR; +/// Modern Unverify discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR; +/// Unverify Sized Collection Item discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +/// Modern Update discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UPDATE_DISCRIMINATOR; +/// Historical Update Metadata Account discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR; +/// Update Metadata Account V2 discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +/// Update Primary Sale Happened Via Token discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR; +/// Modern Use discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_USE_DISCRIMINATOR; +/// Utilize discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_UTILIZE_DISCRIMINATOR; +/// Verify Collection discriminator. +pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR; +/// Modern Verify 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; +/// Crate-root access to `decode` from `instruction`. +pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_decode; +/// Crate-root access to `entry_for_discriminator` from `instruction`. +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; +pub(crate) use self::solana::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_BPF_LOADER_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_CONFIG_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_ED25519_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_FEATURE_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_NATIVE_EVENT_VERSION; +pub(crate) use self::solana::DC_SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_PROTOCOL_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_SECP256R1_MAX_SIGNATURES; +pub(crate) use self::solana::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_SECP256R1_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_SIGNATURE_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_SLASHING_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_STAKE_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_TRACING_TARGET; +pub(crate) use self::solana::DC_SOLANA_CORE_U8_OFFSETS_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_U16_OFFSETS_BYTES; +pub(crate) use self::solana::DC_SOLANA_CORE_VOTE_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE; +pub(crate) use self::solana::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE; +pub(crate) use self::solana::DcSolanaCoreAccountRole; +pub(crate) use self::solana::DcSolanaCoreResolvedInstructionPayload; +pub(crate) use self::solana::decoder_solana_core_address_lookup_table_coverage; +pub(crate) use self::solana::decoder_solana_core_address_lookup_table_decode; +pub(crate) use self::solana::decoder_solana_core_address_lookup_table_recognize; +pub(crate) use self::solana::decoder_solana_core_bounded_hexadecimal_prefix; +pub(crate) use self::solana::decoder_solana_core_bounded_slice; +pub(crate) use self::solana::decoder_solana_core_compute_budget_coverage; +pub(crate) use self::solana::decoder_solana_core_compute_budget_decode; +pub(crate) use self::solana::decoder_solana_core_compute_budget_recognize; +pub(crate) use self::solana::decoder_solana_core_config_coverage; +pub(crate) use self::solana::decoder_solana_core_config_decode; +pub(crate) use self::solana::decoder_solana_core_config_recognize; +pub(crate) use self::solana::decoder_solana_core_decode_instruction_data; +pub(crate) use self::solana::decoder_solana_core_decoded_payload_length; +pub(crate) use self::solana::decoder_solana_core_decoded_payload_sha256; +pub(crate) use self::solana::decoder_solana_core_decoded_result; +pub(crate) use self::solana::decoder_solana_core_failed_result; +pub(crate) use self::solana::decoder_solana_core_feature_coverage; +pub(crate) use self::solana::decoder_solana_core_feature_decode; +pub(crate) use self::solana::decoder_solana_core_feature_recognize; +pub(crate) use self::solana::decoder_solana_core_hash_bytes; +pub(crate) use self::solana::decoder_solana_core_hexadecimal_prefix; +pub(crate) use self::solana::decoder_solana_core_loaders_coverage; +pub(crate) use self::solana::decoder_solana_core_loaders_decode; +pub(crate) use self::solana::decoder_solana_core_loaders_recognize; +pub(crate) use self::solana::decoder_solana_core_payload_hash; +pub(crate) use self::solana::decoder_solana_core_precompiles_coverage; +pub(crate) use self::solana::decoder_solana_core_precompiles_decode; +pub(crate) use self::solana::decoder_solana_core_precompiles_recognize; +pub(crate) use self::solana::decoder_solana_core_read_u32_le; +pub(crate) use self::solana::decoder_solana_core_read_u64_le; +pub(crate) use self::solana::decoder_solana_core_resolve_accounts; +pub(crate) use self::solana::decoder_solana_core_resolve_u8_instruction_payload; +pub(crate) use self::solana::decoder_solana_core_resolve_u16_instruction_payload; +pub(crate) use self::solana::decoder_solana_core_slashing_coverage; +pub(crate) use self::solana::decoder_solana_core_slashing_decode; +pub(crate) use self::solana::decoder_solana_core_slashing_recognize; +pub(crate) use self::solana::decoder_solana_core_stake_coverage; +pub(crate) use self::solana::decoder_solana_core_stake_decode; +pub(crate) use self::solana::decoder_solana_core_stake_recognize; +pub(crate) use self::solana::decoder_solana_core_system_coverage; +pub(crate) use self::solana::decoder_solana_core_system_decode; +pub(crate) use self::solana::decoder_solana_core_system_recognize; +pub(crate) use self::solana::decoder_solana_core_target_outer_instruction_index; +pub(crate) use self::solana::decoder_solana_core_unsupported_result; +pub(crate) use self::solana::decoder_solana_core_vote_coverage; +pub(crate) use self::solana::decoder_solana_core_vote_decode; +pub(crate) use self::solana::decoder_solana_core_vote_recognize; +pub(crate) use self::solana::decoder_solana_core_zk_elgamal_coverage; +pub(crate) use self::solana::decoder_solana_core_zk_elgamal_decode; +pub(crate) use self::solana::decoder_solana_core_zk_elgamal_recognize; +pub(crate) use self::solana::decoder_solana_core_zk_token_proof_coverage; +pub(crate) use self::solana::decoder_solana_core_zk_token_proof_decode; +pub(crate) use self::solana::decoder_solana_core_zk_token_proof_recognize; /// Current stable Associated Token Account decoded event contract version. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_EVENT_VERSION; +pub(crate) use self::spl::DC_SPL_ATA_EVENT_VERSION; /// Exact Associated Token Account instructions published by the official interface. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES; +pub(crate) use self::spl::DC_SPL_ATA_INSTRUCTION_ENTRIES; /// Maximum retained account-key text length for the Associated Token Account decoder. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNT_KEY_BYTES; +pub(crate) use self::spl::DC_SPL_ATA_MAX_ACCOUNT_KEY_BYTES; /// Maximum retained instruction account count for the Associated Token Account decoder. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNTS; +pub(crate) use self::spl::DC_SPL_ATA_MAX_ACCOUNTS; /// Maximum retained semantic diagnostic count for the Associated Token Account decoder. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_DIAGNOSTICS; +pub(crate) use self::spl::DC_SPL_ATA_MAX_DIAGNOSTICS; /// Maximum retained Associated Token Account instruction payload size. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_INSTRUCTION_BYTES; +pub(crate) use self::spl::DC_SPL_ATA_MAX_INSTRUCTION_BYTES; /// Maximum retained transaction account-key count for the Associated Token Account decoder. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_TRANSACTION_KEYS; +pub(crate) use self::spl::DC_SPL_ATA_MAX_TRANSACTION_KEYS; /// Stable protocol and surface code for the Associated Token Account program. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE; +pub(crate) use self::spl::DC_SPL_ATA_SURFACE_CODE; /// Canonical tracing target for the Associated Token Account decoder. -pub(crate) use self::spl::SPL_ASSOCIATED_TOKEN_ACCOUNT_TRACING_TARGET; +pub(crate) use self::spl::DC_SPL_ATA_TRACING_TARGET; /// Current stable SPL ElGamal registry event contract version. -pub(crate) use self::spl::SPL_ELGAMAL_REGISTRY_EVENT_VERSION; +pub(crate) use self::spl::DC_SPL_ELGAMAL_REGISTRY_EVENT_VERSION; /// Maximum retained SPL ElGamal registry instruction payload size. -pub(crate) use self::spl::SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; +pub(crate) use self::spl::DC_SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; /// Stable SPL ElGamal registry surface code. -pub(crate) use self::spl::SPL_ELGAMAL_REGISTRY_SURFACE_CODE; +pub(crate) use self::spl::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE; /// Canonical tracing target for the SPL ElGamal registry decoder. -pub(crate) use self::spl::SPL_ELGAMAL_REGISTRY_TRACING_TARGET; +pub(crate) use self::spl::DC_SPL_ELGAMAL_REGISTRY_TRACING_TARGET; /// Maximum payload prefix retained for bounded diagnostics. -pub(crate) use self::spl::SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::spl::DC_SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; /// Current stable Memo decoded event contract version. -pub(crate) use self::spl::SPL_MEMO_EVENT_VERSION; +pub(crate) use self::spl::DC_SPL_MEMO_EVENT_VERSION; /// Maximum decoded instruction data retained as a complete Memo payload. -pub(crate) use self::spl::SPL_MEMO_MAX_PAYLOAD_BYTES; +pub(crate) use self::spl::DC_SPL_MEMO_MAX_PAYLOAD_BYTES; /// Stable protocol code shared by Memo generations. -pub(crate) use self::spl::SPL_MEMO_PROTOCOL_CODE; +pub(crate) use self::spl::DC_SPL_MEMO_PROTOCOL_CODE; /// Canonical tracing target for the SPL Memo decoder. -pub(crate) use self::spl::SPL_MEMO_TRACING_TARGET; +pub(crate) use self::spl::DC_SPL_MEMO_TRACING_TARGET; /// Stable Memo v1 surface code. -pub(crate) use self::spl::SPL_MEMO_V1_SURFACE_CODE; +pub(crate) use self::spl::DC_SPL_MEMO_V1_SURFACE_CODE; /// Stable Memo v3 surface code. -pub(crate) use self::spl::SPL_MEMO_V3_SURFACE_CODE; +pub(crate) use self::spl::DC_SPL_MEMO_V3_SURFACE_CODE; /// Stable Memo v4 surface code. -pub(crate) use self::spl::SPL_MEMO_V4_SURFACE_CODE; -/// Maximum prefix retained in bounded Token-2022 diagnostics. -pub(crate) use self::spl::SPL_TOKEN_2022_DIAGNOSTIC_PREFIX_BYTES; -/// Current stable Token-2022 decoded event contract version. -pub(crate) use self::spl::SPL_TOKEN_2022_EVENT_VERSION; -/// Exact top-level instruction inventory published by the resolved Token-2022 interface. -pub(crate) use self::spl::SPL_TOKEN_2022_INSTRUCTION_ENTRIES; -/// Maximum total account metas consumed by one Token-2022 batch. -pub(crate) use self::spl::SPL_TOKEN_2022_MAX_BATCH_ACCOUNTS; -/// Maximum decoded sub-instructions in one Token-2022 batch. -pub(crate) use self::spl::SPL_TOKEN_2022_MAX_BATCH_INSTRUCTIONS; -/// Maximum retained Token-2022 instruction payload size. -pub(crate) use self::spl::SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES; -/// Maximum retained UTF-8 string size for embedded Token Metadata instructions. -pub(crate) use self::spl::SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES; -/// Stable Token-2022 surface code. -pub(crate) use self::spl::SPL_TOKEN_2022_SURFACE_CODE; -/// Canonical tracing target for the Token-2022 decoder. -pub(crate) use self::spl::SPL_TOKEN_2022_TRACING_TARGET; +pub(crate) use self::spl::DC_SPL_MEMO_V4_SURFACE_CODE; /// Maximum prefix retained in bounded classic SPL Token diagnostics. -pub(crate) use self::spl::SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::spl::DC_SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; /// Current stable classic SPL Token decoded event contract version. -pub(crate) use self::spl::SPL_TOKEN_EVENT_VERSION; +pub(crate) use self::spl::DC_SPL_TOKEN_EVENT_VERSION; /// One exact classic SPL Token instruction entry published by the official interface. -pub(crate) use self::spl::SPL_TOKEN_INSTRUCTION_ENTRIES; +pub(crate) use self::spl::DC_SPL_TOKEN_INSTRUCTION_ENTRIES; /// Maximum total account metas consumed by one classic SPL Token batch. -pub(crate) use self::spl::SPL_TOKEN_MAX_BATCH_ACCOUNTS; +pub(crate) use self::spl::DC_SPL_TOKEN_MAX_BATCH_ACCOUNTS; /// Maximum decoded sub-instructions in one classic SPL Token batch. -pub(crate) use self::spl::SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; +pub(crate) use self::spl::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; /// Maximum retained classic SPL Token instruction payload size. -pub(crate) use self::spl::SPL_TOKEN_MAX_INSTRUCTION_BYTES; +pub(crate) use self::spl::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES; /// Stable protocol and surface code for the classic SPL Token program. -pub(crate) use self::spl::SPL_TOKEN_SURFACE_CODE; +pub(crate) use self::spl::DC_SPL_TOKEN_SURFACE_CODE; /// Canonical tracing target for the classic SPL Token decoder. -pub(crate) use self::spl::SPL_TOKEN_TRACING_TARGET; +pub(crate) use self::spl::DC_SPL_TOKEN_TRACING_TARGET; +/// Maximum prefix retained in bounded Token-2022 diagnostics. +pub(crate) use self::spl::DC_SPL_TOKEN2022_DIAGNOSTIC_PREFIX_BYTES; +/// Current stable Token-2022 decoded event contract version. +pub(crate) use self::spl::DC_SPL_TOKEN2022_EVENT_VERSION; +/// Exact top-level instruction inventory published by the resolved Token-2022 interface. +pub(crate) use self::spl::DC_SPL_TOKEN2022_INSTRUCTION_ENTRIES; +/// Maximum total account metas consumed by one Token-2022 batch. +pub(crate) use self::spl::DC_SPL_TOKEN2022_MAX_BATCH_ACCOUNTS; +/// Maximum decoded sub-instructions in one Token-2022 batch. +pub(crate) use self::spl::DC_SPL_TOKEN2022_MAX_BATCH_INSTRUCTIONS; +/// Maximum retained Token-2022 instruction payload size. +pub(crate) use self::spl::DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES; +/// Maximum retained UTF-8 string size for embedded Token Metadata instructions. +pub(crate) use self::spl::DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES; +/// Stable Token-2022 surface code. +pub(crate) use self::spl::DC_SPL_TOKEN2022_SURFACE_CODE; +/// Canonical tracing target for the Token-2022 decoder. +pub(crate) use self::spl::DC_SPL_TOKEN2022_TRACING_TARGET; +/// One parsed SPL ElGamal registry instruction. +pub(crate) use self::spl::DcSplElGamalRegistryParsedRegistryInstruction; /// Decodes one bounded Associated Token Account instruction. -pub(crate) use self::spl::spl_associated_token_account_decode; +pub(crate) use self::spl::decoder_spl_associated_token_account_decode; /// Returns the exact entry matching an Associated Token Account wire. -pub(crate) use self::spl::spl_associated_token_account_entry; +pub(crate) use self::spl::decoder_spl_associated_token_account_entry; /// Reads one bounded Associated Token Account payload. -pub(crate) use self::spl::spl_associated_token_account_payload; +pub(crate) use self::spl::decoder_spl_associated_token_account_payload; /// Decodes one bounded SPL ElGamal registry instruction. -pub(crate) use self::spl::spl_elgamal_registry_decode; +pub(crate) use self::spl::decoder_spl_elgamal_registry_decode; /// Decodes one bounded SPL ElGamal registry instruction payload. -pub(crate) use self::spl::spl_elgamal_registry_decode_payload; +pub(crate) use self::spl::decoder_spl_elgamal_registry_decode_payload; /// Parses one exact SPL ElGamal registry instruction. -pub(crate) use self::spl::spl_elgamal_registry_parse; +pub(crate) use self::spl::decoder_spl_elgamal_registry_parse; /// Decodes one bounded SPL Memo instruction. -pub(crate) use self::spl::spl_memo_decode; -/// Decodes one bounded Token-2022 instruction. -pub(crate) use self::spl::spl_token_2022_decode; -/// Returns the exact entry matching one Token-2022 tag. -pub(crate) use self::spl::spl_token_2022_entry_for_tag; -/// Returns the first byte of one retained Token-2022 payload. -pub(crate) use self::spl::spl_token_2022_payload_tag; +pub(crate) use self::spl::decoder_spl_memo_decode; /// Decodes one bounded classic SPL Token instruction. -pub(crate) use self::spl::spl_token_decode; +pub(crate) use self::spl::decoder_spl_token_decode; /// Returns the published entry matching one classic SPL Token tag. -pub(crate) use self::spl::spl_token_entry_for_tag; +pub(crate) use self::spl::decoder_spl_token_entry_for_tag; /// Returns the first byte of one retained classic SPL Token payload. -pub(crate) use self::spl::spl_token_payload_tag; +pub(crate) use self::spl::decoder_spl_token_payload_tag; +/// Decodes one bounded Token-2022 instruction. +pub(crate) use self::spl::decoder_spl_token2022_decode; +/// Returns the exact entry matching one Token-2022 tag. +pub(crate) use self::spl::decoder_spl_token2022_entry_for_tag; +/// Returns the first byte of one retained Token-2022 payload. +pub(crate) use self::spl::decoder_spl_token2022_payload_tag; +/// Current contextual core instruction input contract version. +pub use self::api::DC_API_CORE_INSTRUCTION_INPUT_CONTRACT_VERSION; +/// Stable contextual decoded observation. +pub use self::api::DcApiDecodedObservation; +/// Machine-readable decoder coverage declaration. +pub use self::api::DcApiDecoderCoverageDeclaration; +/// Declared decoder coverage entry kind. +pub use self::api::DcApiDecoderCoverageEntryKind; +/// Structured decoder diagnostic. +pub use self::api::DcApiDecoderDiagnostic; +/// Complete decoder execution result. +pub use self::api::DcApiDecoderExecutionResult; +/// Stable decoder identity. +pub use self::api::DcApiDecoderIdentity; +/// Decoder terminal result status. +pub use self::api::DcApiDecoderOutcomeStatus; +/// Explicit decoding proof. +pub use self::api::DcApiDecoderProof; +/// Decoding proof category. +pub use self::api::DcApiDecoderProofKind; +/// Deterministic decoder recognition result. +pub use self::api::DcApiDecoderRecognition; +/// Exposes the decoder support level. +pub use self::api::DcApiDecoderSupport; +/// One statically declared decoder surface. +pub use self::api::DcApiDecoderSurface; +/// Initial decoder implementation placeholder for API-level tests. +pub use self::api::DcApiInitialDecoder; +/// Contextual instruction decoder contract. +pub use self::api::DcApiInstructionDecoder; +/// Exposes the common protocol decoder trait. +pub use self::api::DcApiProtocolDecoder; +/// Computes the deterministic contextual input hash. +pub use self::api::decoder_api_decoder_api_contextual_input_hash; +/// Returns true when a decoder declares the exact program id. +pub use self::api::decoder_api_decoder_handles_program_id; +/// Computes a deterministic lowercase SHA-256 hash for one JSON value. +pub use self::api::decoder_api_deterministic_json_hash; +/// Extracts the first eight payload bytes as hexadecimal when available. +pub use self::api::decoder_api_discriminator_8_hex; +/// Exhaustive published Metaplex account-key inventory. +pub use self::metadata::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT; /// Exact decoder for the Metaplex Token Metadata program. -pub use self::metadata::MetadataMetaplexTokenMetadataDecoder; +pub use self::metadata::DcMetadataMetaplexTokenMetadataDecoder; +/// Canonical projection shared by Collection and Use Authority records. +pub use self::metadata::DcMetadataMtmAuthorityRecordAccountSnapshot; +/// Stable identity and policy of one canonical account snapshot. +pub use self::metadata::DcMetadataMtmCanonicalAccountIdentity; +/// Lifecycle class of one canonical account layout. +pub use self::metadata::DcMetadataMtmCanonicalAccountLifecycle; +/// Provenance retained for one canonical account observation. +pub use self::metadata::DcMetadataMtmCanonicalAccountProvenance; +/// Execution policy separated from historical materialization. +pub use self::metadata::DcMetadataMtmCanonicalExecutionPolicy; +/// Materialization policy for active or historical state. +pub use self::metadata::DcMetadataMtmCanonicalMaterializationPolicy; +/// Canonical account envelope used by materializers and replay. +pub use self::metadata::DcMetadataMtmCanonicalMetadataAccountSnapshot; +/// Typed canonical Metaplex account state. +pub use self::metadata::DcMetadataMtmCanonicalMetadataAccountState; +/// Origin of one canonical account observation. +pub use self::metadata::DcMetadataMtmCanonicalObservationSource; +/// Canonical projection shared by Metadata and Holder delegate records. +pub use self::metadata::DcMetadataMtmDelegateRecordAccountSnapshot; +/// Supported edition account layout. +pub use self::metadata::DcMetadataMtmEditionAccountKind; +/// Canonical bounded projection of one edition or master-edition account. +pub use self::metadata::DcMetadataMtmEditionAccountSnapshot; +/// Supported Edition Marker account layout. +pub use self::metadata::DcMetadataMtmEditionMarkerAccountKind; +/// Canonical bounded projection of one Edition Marker account. +pub use self::metadata::DcMetadataMtmEditionMarkerAccountSnapshot; +/// Bounded error returned while decoding a Metadata account. +pub use self::metadata::DcMetadataMtmMetadataAccountDecodeError; +/// One entry in the exhaustive published account-key audit. +pub use self::metadata::DcMetadataMtmMetadataAccountLayoutAuditEntry; +/// Canonical bounded projection of one Metadata account. +pub use self::metadata::DcMetadataMtmMetadataAccountSnapshot; +/// One bounded historical reservation entry. +pub use self::metadata::DcMetadataMtmReservationEntrySnapshot; +/// Historical Reservation List account generation. +pub use self::metadata::DcMetadataMtmReservationListAccountKind; +/// Canonical decode-only projection of a historical Reservation List account. +pub use self::metadata::DcMetadataMtmReservationListAccountSnapshot; +/// Canonical projection of one Token Owned Escrow account. +pub use self::metadata::DcMetadataMtmTokenOwnedEscrowAccountSnapshot; +/// Authority form used by one Token Owned Escrow account. +pub use self::metadata::DcMetadataMtmTokenOwnedEscrowAuthorityKind; +/// Canonical bounded projection of one programmable Token Record account. +pub use self::metadata::DcMetadataMtmTokenRecordAccountSnapshot; +/// Decodes one Collection Authority Record account. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_collection_authority_record_account; +/// Decodes and validates one edition or master-edition account snapshot. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_edition_account; +/// Decodes and validates one Edition Marker account snapshot. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account; +/// Decodes one Holder Delegate Record account. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_holder_delegate_record_account; +/// Decodes and validates one canonical Metadata account snapshot. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_metadata_account; +/// Decodes one Metadata Delegate Record account. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_metadata_delegate_record_account; +/// Decodes one historical Reservation List V1 or V2 account. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account; +/// Decodes one Token Owned Escrow account. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account; +/// Decodes and validates one programmable Token Record account snapshot. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_token_record_account; +/// Decodes one Use Authority Record account. +pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account; +/// Runtime-native Solana decoder with phased maximal native coverage. +pub use self::solana::DcSolanaCoreDecoder; /// Exact byte length of one SPL ElGamal registry account. -pub use self::spl::ELGAMAL_REGISTRY_ACCOUNT_LEN; -/// Parsed SPL ElGamal public-key registry account. -pub use self::spl::ElGamalRegistryState; +pub use self::spl::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN; /// Exact decoder for the SPL Associated Token Account program. -pub use self::spl::SplAssociatedTokenAccountDecoder; +pub use self::spl::DcSplAssociatedTokenAccountDecoder; +/// Parsed SPL ElGamal public-key registry account. +pub use self::spl::DcSplElGamalRegistryState; /// Exact decoder for the SPL ElGamal registry program. -pub use self::spl::SplElgamalRegistryDecoder; +pub use self::spl::DcSplElgamalRegistryDecoder; /// Exact decoder for the three registered SPL Memo generations. -pub use self::spl::SplMemoDecoder; +pub use self::spl::DcSplMemoDecoder; /// Exact decoder for the Token-2022 program. -pub use self::spl::SplToken2022Decoder; +pub use self::spl::DcSplToken2022Decoder; /// Exact decoder for the classic SPL Token program. -pub use self::spl::SplTokenDecoder; +pub use self::spl::DcSplTokenDecoder; /// Parsed Token-2022 Mint, Account, or Multisig state. -pub use self::spl::Token2022State; +pub use self::spl::DcToken2022State; /// Exact Token-2022 base account state kind. -pub use self::spl::Token2022StateKind; +pub use self::spl::DcToken2022StateKind; /// One exact Token-2022 TLV entry. -pub use self::spl::Token2022TlvEntry; +pub use self::spl::DcToken2022TlvEntry; /// Parses one exact SPL ElGamal registry account. -pub use self::spl::parse_elgamal_registry_state; +pub use self::spl::decoder_spl_elgamal_registry_parse_elgamal_registry_state; /// Parses one Token-2022 Mint, Account, or Multisig state. -pub use self::spl::parse_token_2022_state; +pub use self::spl::decoder_spl_token2022_parse_token2022_state; diff --git a/kb-lib/src/decoder/adapter.rs b/kb-lib/src/decoder/adapter.rs index ca70eed..f6d1336 100644 --- a/kb-lib/src/decoder/adapter.rs +++ b/kb-lib/src/decoder/adapter.rs @@ -3,4 +3,4 @@ //! `adapter` decoder family. -pub mod saber_decimal_wrapper; +mod saber_decimal_wrapper; diff --git a/kb-lib/src/decoder/adapter/saber_decimal_wrapper.rs b/kb-lib/src/decoder/adapter/saber_decimal_wrapper.rs index 00d06f4..348f001 100644 --- a/kb-lib/src/decoder/adapter/saber_decimal_wrapper.rs +++ b/kb-lib/src/decoder/adapter/saber_decimal_wrapper.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_adapter_saber_decimal_wrapper`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_adapter_saber_decimal_wrapper"; +const LEGACY_CRATE: &str = "kb_decoder_adapter_saber_decimal_wrapper"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/admin.rs b/kb-lib/src/decoder/admin.rs index 9ccca03..671be3c 100644 --- a/kb-lib/src/decoder/admin.rs +++ b/kb-lib/src/decoder/admin.rs @@ -3,5 +3,5 @@ //! `admin` decoder family. -pub mod jupiter_lock; -pub mod pump_fees; +mod jupiter_lock; +mod pump_fees; diff --git a/kb-lib/src/decoder/admin/jupiter_lock.rs b/kb-lib/src/decoder/admin/jupiter_lock.rs index 8895fbf..1364b72 100644 --- a/kb-lib/src/decoder/admin/jupiter_lock.rs +++ b/kb-lib/src/decoder/admin/jupiter_lock.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_admin_jupiter_lock`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_admin_jupiter_lock"; +const LEGACY_CRATE: &str = "kb_decoder_admin_jupiter_lock"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/admin/pump_fees.rs b/kb-lib/src/decoder/admin/pump_fees.rs index da344e1..c94c4cb 100644 --- a/kb-lib/src/decoder/admin/pump_fees.rs +++ b/kb-lib/src/decoder/admin/pump_fees.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_admin_pump_fees`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_admin_pump_fees"; +const LEGACY_CRATE: &str = "kb_decoder_admin_pump_fees"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm.rs b/kb-lib/src/decoder/amm.rs index 74d2d79..9560350 100644 --- a/kb-lib/src/decoder/amm.rs +++ b/kb-lib/src/decoder/amm.rs @@ -3,29 +3,29 @@ //! `amm` decoder family. -pub mod aldrin_v1; -pub mod aldrin_v2; -pub mod alphaq; -pub mod believe; -pub mod bonk_swap; -pub mod fluxbeam; -pub mod goon_fi; -pub mod goosefx_gamma; -pub mod goosefx_v2; -pub mod guac_swap; -pub mod lifinity_swap_v2; -pub mod metadao_futarchy_amm; -pub mod metadao_v0_5; -pub mod meteora_damm_v1; -pub mod meteora_damm_v2; -pub mod obric_v2; -pub mod one_dex; -pub mod pump_swap; -pub mod raydium_lp_v4; -pub mod solfi; -pub mod solfi_v2; -pub mod vertigo; -pub mod virtuals; -pub mod woofi; -pub mod zero_fi; -pub mod zora; +mod aldrin_v1; +mod aldrin_v2; +mod alphaq; +mod believe; +mod bonk_swap; +mod fluxbeam; +mod goon_fi; +mod goosefx_gamma; +mod goosefx_v2; +mod guac_swap; +mod lifinity_swap_v2; +mod metadao_futarchy_amm; +mod metadao_v0_5; +mod meteora_damm_v1; +mod meteora_damm_v2; +mod obric_v2; +mod one_dex; +mod pump_swap; +mod raydium_lp_v4; +mod solfi; +mod solfi_v2; +mod vertigo; +mod virtuals; +mod woofi; +mod zero_fi; +mod zora; diff --git a/kb-lib/src/decoder/amm/aldrin_v1.rs b/kb-lib/src/decoder/amm/aldrin_v1.rs index 35b6c97..c59f5da 100644 --- a/kb-lib/src/decoder/amm/aldrin_v1.rs +++ b/kb-lib/src/decoder/amm/aldrin_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_aldrin_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_aldrin_v1"; +const LEGACY_CRATE: &str = "kb_decoder_amm_aldrin_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/aldrin_v2.rs b/kb-lib/src/decoder/amm/aldrin_v2.rs index da05b00..c9f848b 100644 --- a/kb-lib/src/decoder/amm/aldrin_v2.rs +++ b/kb-lib/src/decoder/amm/aldrin_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_aldrin_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_aldrin_v2"; +const LEGACY_CRATE: &str = "kb_decoder_amm_aldrin_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/alphaq.rs b/kb-lib/src/decoder/amm/alphaq.rs index 3be8b6f..6dda808 100644 --- a/kb-lib/src/decoder/amm/alphaq.rs +++ b/kb-lib/src/decoder/amm/alphaq.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_alphaq`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_alphaq"; +const LEGACY_CRATE: &str = "kb_decoder_amm_alphaq"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/believe.rs b/kb-lib/src/decoder/amm/believe.rs index 4f0aef3..9681f27 100644 --- a/kb-lib/src/decoder/amm/believe.rs +++ b/kb-lib/src/decoder/amm/believe.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_believe`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_believe"; +const LEGACY_CRATE: &str = "kb_decoder_amm_believe"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/bonk_swap.rs b/kb-lib/src/decoder/amm/bonk_swap.rs index 73cd749..2411554 100644 --- a/kb-lib/src/decoder/amm/bonk_swap.rs +++ b/kb-lib/src/decoder/amm/bonk_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_bonk_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_bonk_swap"; +const LEGACY_CRATE: &str = "kb_decoder_amm_bonk_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/fluxbeam.rs b/kb-lib/src/decoder/amm/fluxbeam.rs index c9e1561..14bd937 100644 --- a/kb-lib/src/decoder/amm/fluxbeam.rs +++ b/kb-lib/src/decoder/amm/fluxbeam.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_fluxbeam`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_fluxbeam"; +const LEGACY_CRATE: &str = "kb_decoder_amm_fluxbeam"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/goon_fi.rs b/kb-lib/src/decoder/amm/goon_fi.rs index de23f47..c1b3d05 100644 --- a/kb-lib/src/decoder/amm/goon_fi.rs +++ b/kb-lib/src/decoder/amm/goon_fi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_goon_fi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_goon_fi"; +const LEGACY_CRATE: &str = "kb_decoder_amm_goon_fi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/goosefx_gamma.rs b/kb-lib/src/decoder/amm/goosefx_gamma.rs index deee864..a6d4dc0 100644 --- a/kb-lib/src/decoder/amm/goosefx_gamma.rs +++ b/kb-lib/src/decoder/amm/goosefx_gamma.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_goosefx_gamma`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_goosefx_gamma"; +const LEGACY_CRATE: &str = "kb_decoder_amm_goosefx_gamma"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/goosefx_v2.rs b/kb-lib/src/decoder/amm/goosefx_v2.rs index caf2c50..436909b 100644 --- a/kb-lib/src/decoder/amm/goosefx_v2.rs +++ b/kb-lib/src/decoder/amm/goosefx_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_goosefx_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_goosefx_v2"; +const LEGACY_CRATE: &str = "kb_decoder_amm_goosefx_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/guac_swap.rs b/kb-lib/src/decoder/amm/guac_swap.rs index e312008..f5766ea 100644 --- a/kb-lib/src/decoder/amm/guac_swap.rs +++ b/kb-lib/src/decoder/amm/guac_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_guac_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_guac_swap"; +const LEGACY_CRATE: &str = "kb_decoder_amm_guac_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/lifinity_swap_v2.rs b/kb-lib/src/decoder/amm/lifinity_swap_v2.rs index 938cfe8..229c16c 100644 --- a/kb-lib/src/decoder/amm/lifinity_swap_v2.rs +++ b/kb-lib/src/decoder/amm/lifinity_swap_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_lifinity_swap_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_lifinity_swap_v2"; +const LEGACY_CRATE: &str = "kb_decoder_amm_lifinity_swap_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/metadao_futarchy_amm.rs b/kb-lib/src/decoder/amm/metadao_futarchy_amm.rs index b859227..ae60d50 100644 --- a/kb-lib/src/decoder/amm/metadao_futarchy_amm.rs +++ b/kb-lib/src/decoder/amm/metadao_futarchy_amm.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_metadao_futarchy_amm`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_metadao_futarchy_amm"; +const LEGACY_CRATE: &str = "kb_decoder_amm_metadao_futarchy_amm"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/metadao_v0_5.rs b/kb-lib/src/decoder/amm/metadao_v0_5.rs index f1e0619..d45301b 100644 --- a/kb-lib/src/decoder/amm/metadao_v0_5.rs +++ b/kb-lib/src/decoder/amm/metadao_v0_5.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_metadao_v0_5`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_metadao_v0_5"; +const LEGACY_CRATE: &str = "kb_decoder_amm_metadao_v0_5"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/meteora_damm_v1.rs b/kb-lib/src/decoder/amm/meteora_damm_v1.rs index 97a5f68..ed3e442 100644 --- a/kb-lib/src/decoder/amm/meteora_damm_v1.rs +++ b/kb-lib/src/decoder/amm/meteora_damm_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_meteora_damm_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_meteora_damm_v1"; +const LEGACY_CRATE: &str = "kb_decoder_amm_meteora_damm_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/meteora_damm_v2.rs b/kb-lib/src/decoder/amm/meteora_damm_v2.rs index a451730..e2f5a78 100644 --- a/kb-lib/src/decoder/amm/meteora_damm_v2.rs +++ b/kb-lib/src/decoder/amm/meteora_damm_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_meteora_damm_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_meteora_damm_v2"; +const LEGACY_CRATE: &str = "kb_decoder_amm_meteora_damm_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/obric_v2.rs b/kb-lib/src/decoder/amm/obric_v2.rs index 6af2996..1019ce1 100644 --- a/kb-lib/src/decoder/amm/obric_v2.rs +++ b/kb-lib/src/decoder/amm/obric_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_obric_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_obric_v2"; +const LEGACY_CRATE: &str = "kb_decoder_amm_obric_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/one_dex.rs b/kb-lib/src/decoder/amm/one_dex.rs index c1007a4..3d3033d 100644 --- a/kb-lib/src/decoder/amm/one_dex.rs +++ b/kb-lib/src/decoder/amm/one_dex.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_one_dex`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_one_dex"; +const LEGACY_CRATE: &str = "kb_decoder_amm_one_dex"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/pump_swap.rs b/kb-lib/src/decoder/amm/pump_swap.rs index a32b64c..79a7c8c 100644 --- a/kb-lib/src/decoder/amm/pump_swap.rs +++ b/kb-lib/src/decoder/amm/pump_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_pump_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_pump_swap"; +const LEGACY_CRATE: &str = "kb_decoder_amm_pump_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/raydium_lp_v4.rs b/kb-lib/src/decoder/amm/raydium_lp_v4.rs index e0d50ee..7d7157f 100644 --- a/kb-lib/src/decoder/amm/raydium_lp_v4.rs +++ b/kb-lib/src/decoder/amm/raydium_lp_v4.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_raydium_lp_v4`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_raydium_lp_v4"; +const LEGACY_CRATE: &str = "kb_decoder_amm_raydium_lp_v4"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/solfi.rs b/kb-lib/src/decoder/amm/solfi.rs index 4e3fb65..4a5803b 100644 --- a/kb-lib/src/decoder/amm/solfi.rs +++ b/kb-lib/src/decoder/amm/solfi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_solfi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_solfi"; +const LEGACY_CRATE: &str = "kb_decoder_amm_solfi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/solfi_v2.rs b/kb-lib/src/decoder/amm/solfi_v2.rs index 2901585..8469ecf 100644 --- a/kb-lib/src/decoder/amm/solfi_v2.rs +++ b/kb-lib/src/decoder/amm/solfi_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_solfi_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_solfi_v2"; +const LEGACY_CRATE: &str = "kb_decoder_amm_solfi_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/vertigo.rs b/kb-lib/src/decoder/amm/vertigo.rs index 20d79ab..03573d3 100644 --- a/kb-lib/src/decoder/amm/vertigo.rs +++ b/kb-lib/src/decoder/amm/vertigo.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_vertigo`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_vertigo"; +const LEGACY_CRATE: &str = "kb_decoder_amm_vertigo"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/virtuals.rs b/kb-lib/src/decoder/amm/virtuals.rs index f7515c0..c4085fa 100644 --- a/kb-lib/src/decoder/amm/virtuals.rs +++ b/kb-lib/src/decoder/amm/virtuals.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_virtuals`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_virtuals"; +const LEGACY_CRATE: &str = "kb_decoder_amm_virtuals"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/woofi.rs b/kb-lib/src/decoder/amm/woofi.rs index 2e31857..26f7cd3 100644 --- a/kb-lib/src/decoder/amm/woofi.rs +++ b/kb-lib/src/decoder/amm/woofi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_woofi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_woofi"; +const LEGACY_CRATE: &str = "kb_decoder_amm_woofi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/zero_fi.rs b/kb-lib/src/decoder/amm/zero_fi.rs index 031e0c1..89dcde4 100644 --- a/kb-lib/src/decoder/amm/zero_fi.rs +++ b/kb-lib/src/decoder/amm/zero_fi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_zero_fi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_zero_fi"; +const LEGACY_CRATE: &str = "kb_decoder_amm_zero_fi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/amm/zora.rs b/kb-lib/src/decoder/amm/zora.rs index a204a63..c70003e 100644 --- a/kb-lib/src/decoder/amm/zora.rs +++ b/kb-lib/src/decoder/amm/zora.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_amm_zora`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_amm_zora"; +const LEGACY_CRATE: &str = "kb_decoder_amm_zora"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/anchor.rs b/kb-lib/src/decoder/anchor.rs index e775a2c..2a52d7a 100644 --- a/kb-lib/src/decoder/anchor.rs +++ b/kb-lib/src/decoder/anchor.rs @@ -3,4 +3,4 @@ //! `anchor` decoder family. -pub mod core; +mod core; diff --git a/kb-lib/src/decoder/anchor/core.rs b/kb-lib/src/decoder/anchor/core.rs index 4c2eaaa..5f8aced 100644 --- a/kb-lib/src/decoder/anchor/core.rs +++ b/kb-lib/src/decoder/anchor/core.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_anchor`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_anchor"; +const LEGACY_CRATE: &str = "kb_decoder_anchor"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/api.rs b/kb-lib/src/decoder/api.rs index 0a95548..5553a24 100644 --- a/kb-lib/src/decoder/api.rs +++ b/kb-lib/src/decoder/api.rs @@ -3,45 +3,46 @@ //! Decoder contracts consolidated from `kb_decoder_api`. -pub mod contracts; -pub mod decoder; +mod contracts; +mod decoder; + /// Current contextual core instruction input contract version. -pub use crate::decoder::api::contracts::CORE_INSTRUCTION_INPUT_CONTRACT_VERSION; +pub use self::contracts::DC_API_CORE_INSTRUCTION_INPUT_CONTRACT_VERSION; /// Stable contextual decoded observation. -pub use crate::decoder::api::contracts::DecodedObservation; +pub use self::contracts::DcApiDecodedObservation; /// Machine-readable decoder coverage declaration. -pub use crate::decoder::api::contracts::DecoderCoverageDeclaration; +pub use self::contracts::DcApiDecoderCoverageDeclaration; /// Declared decoder coverage entry kind. -pub use crate::decoder::api::contracts::DecoderCoverageEntryKind; +pub use self::contracts::DcApiDecoderCoverageEntryKind; /// Structured decoder diagnostic. -pub use crate::decoder::api::contracts::DecoderDiagnostic; +pub use self::contracts::DcApiDecoderDiagnostic; /// Complete decoder execution result. -pub use crate::decoder::api::contracts::DecoderExecutionResult; +pub use self::contracts::DcApiDecoderExecutionResult; /// Stable decoder identity. -pub use crate::decoder::api::contracts::DecoderIdentity; +pub use self::contracts::DcApiDecoderIdentity; /// Decoder terminal result status. -pub use crate::decoder::api::contracts::DecoderOutcomeStatus; +pub use self::contracts::DcApiDecoderOutcomeStatus; /// Explicit decoding proof. -pub use crate::decoder::api::contracts::DecoderProof; +pub use self::contracts::DcApiDecoderProof; /// Decoding proof category. -pub use crate::decoder::api::contracts::DecoderProofKind; +pub use self::contracts::DcApiDecoderProofKind; /// Deterministic decoder recognition result. -pub use crate::decoder::api::contracts::DecoderRecognition; +pub use self::contracts::DcApiDecoderRecognition; /// One statically declared decoder surface. -pub use crate::decoder::api::contracts::DecoderSurface; +pub use self::contracts::DcApiDecoderSurface; /// Contextual instruction decoder contract. -pub use crate::decoder::api::contracts::InstructionDecoder; +pub use self::contracts::DcApiInstructionDecoder; /// Computes the deterministic contextual input hash. -pub use crate::decoder::api::contracts::contextual_input_hash; +pub use self::contracts::decoder_api_decoder_api_contextual_input_hash; /// Returns true when a decoder declares the exact program id. -pub use crate::decoder::api::contracts::decoder_handles_program_id; +pub use self::contracts::decoder_api_decoder_handles_program_id; /// Computes a deterministic lowercase SHA-256 hash for one JSON value. -pub use crate::decoder::api::contracts::deterministic_json_hash; +pub use self::contracts::decoder_api_deterministic_json_hash; /// Extracts the first eight payload bytes as hexadecimal when available. -pub use crate::decoder::api::contracts::discriminator_8_hex; +pub use self::contracts::decoder_api_discriminator_8_hex; /// Exposes the decoder support level. -pub use crate::decoder::api::decoder::DecoderSupport; +pub use self::decoder::DcApiDecoderSupport; /// Initial decoder implementation placeholder for API-level tests. -pub use crate::decoder::api::decoder::InitialDecoder; +pub use self::decoder::DcApiInitialDecoder; /// Exposes the common protocol decoder trait. -pub use crate::decoder::api::decoder::ProtocolDecoder; +pub use self::decoder::DcApiProtocolDecoder; diff --git a/kb-lib/src/decoder/api/contracts.rs b/kb-lib/src/decoder/api/contracts.rs index b7d4fb0..7e31de3 100644 --- a/kb-lib/src/decoder/api/contracts.rs +++ b/kb-lib/src/decoder/api/contracts.rs @@ -6,18 +6,19 @@ use sha2::Digest; // rust-rules: trait-import /// Current contextual core instruction input contract version. -pub const CORE_INSTRUCTION_INPUT_CONTRACT_VERSION: u32 = crate::CORE_REPLAY_INPUT_CONTRACT_VERSION; +pub const DC_API_CORE_INSTRUCTION_INPUT_CONTRACT_VERSION: u32 = + crate::MD_CORE_REPLAY_INPUT_CONTRACT_VERSION; /// Stable identity of one contextual instruction decoder. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct DecoderIdentity { +pub struct DcApiDecoderIdentity { /// Stable lower snake case processor name. pub name: std::string::String, /// Semantic or deterministic implementation version. pub version: std::string::String, } -impl DecoderIdentity { +impl DcApiDecoderIdentity { /// Builds a validated decoder identity. pub fn new( name: impl std::convert::Into, @@ -38,7 +39,7 @@ impl DecoderIdentity { /// One statically declared Solana surface supported by a decoder. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct DecoderSurface { +pub struct DcApiDecoderSurface { /// Exact Solana program identifier. pub program_id: &'static str, /// Stable surface code. @@ -49,7 +50,7 @@ pub struct DecoderSurface { /// Declared decoder coverage entry kind. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub enum DecoderCoverageEntryKind { +pub enum DcApiDecoderCoverageEntryKind { /// Program instruction entry. Instruction, /// Program event entry. @@ -60,13 +61,13 @@ pub enum DecoderCoverageEntryKind { /// Machine-readable decoder coverage declaration. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct DecoderCoverageDeclaration { +pub struct DcApiDecoderCoverageDeclaration { /// Solana program identifier. pub program_id: std::string::String, /// Optional stable surface code. pub surface_code: std::option::Option, /// Entry kind. - pub entry_kind: DecoderCoverageEntryKind, + pub entry_kind: DcApiDecoderCoverageEntryKind, /// Stable instruction, event or discriminator code. pub entry_code: std::string::String, /// Optional normalized lowercase hexadecimal discriminator. @@ -75,12 +76,12 @@ pub struct DecoderCoverageDeclaration { pub historical: bool, } -impl DecoderCoverageDeclaration { +impl DcApiDecoderCoverageDeclaration { /// Builds a validated coverage declaration. pub fn new( program_id: impl std::convert::Into, surface_code: std::option::Option, - entry_kind: DecoderCoverageEntryKind, + entry_kind: DcApiDecoderCoverageEntryKind, entry_code: impl std::convert::Into, discriminator_hex: std::option::Option, historical: bool, @@ -122,7 +123,7 @@ impl DecoderCoverageDeclaration { /// Deterministic recognition result used by dispatch. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct DecoderRecognition { +pub struct DcApiDecoderRecognition { /// Whether the decoder is compatible with the input. pub compatible: bool, /// Whether recognition is exact rather than program-only. @@ -137,7 +138,7 @@ pub struct DecoderRecognition { pub discriminator_hex: std::option::Option, } -impl DecoderRecognition { +impl DcApiDecoderRecognition { /// Builds a non-compatible recognition result. pub fn incompatible() -> Self { return Self { @@ -171,7 +172,7 @@ impl DecoderRecognition { /// Decoder terminal result status. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub enum DecoderOutcomeStatus { +pub enum DcApiDecoderOutcomeStatus { /// At least one stable decoded observation was produced. Decoded, /// The decoder intentionally ignored a recognized input. @@ -184,7 +185,7 @@ pub enum DecoderOutcomeStatus { /// Proof category attached to one decoded observation. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub enum DecoderProofKind { +pub enum DcApiDecoderProofKind { /// Exact instruction discriminator match. ExactDiscriminator, /// Exact binary layout decode. @@ -207,18 +208,18 @@ pub enum DecoderProofKind { /// Explicit proof attached to one decoded observation. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct DecoderProof { +pub struct DcApiDecoderProof { /// Proof category. - pub kind: DecoderProofKind, + pub kind: DcApiDecoderProofKind, /// Decoder confidence. - pub confidence: crate::DecoderConfidence, + pub confidence: crate::MdDecoderConfidence, /// Stable evidence strings, hashes or classifier codes. pub evidence: std::vec::Vec, } /// Structured decoder diagnostic without third-party error wrappers. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct DecoderDiagnostic { +pub struct DcApiDecoderDiagnostic { /// Stable machine-readable diagnostic code. pub code: std::string::String, /// Human-readable diagnostic message. @@ -227,7 +228,7 @@ pub struct DecoderDiagnostic { pub retriable: bool, } -impl DecoderDiagnostic { +impl DcApiDecoderDiagnostic { /// Builds a validated decoder diagnostic. pub fn new( code: impl std::convert::Into, @@ -250,11 +251,11 @@ impl DecoderDiagnostic { /// Stable contextual decoded observation persisted by the decode pipeline. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct DecodedObservation { +pub struct DcApiDecodedObservation { /// Stable processor-owned event key within one input. pub event_key: std::string::String, /// Shared typed protocol event identity. - pub event: crate::DecodedProtocolEvent, + pub event: crate::MdDecodedProtocolEvent, /// Typed event payload serialized as deterministic JSON. pub payload_json: serde_json::Value, /// Whether the source transaction failed on-chain. @@ -264,10 +265,10 @@ pub struct DecodedObservation { /// Whether the observed state mutation was committed on-chain. pub observation_committed: bool, /// Explicit decoding proof. - pub proof: DecoderProof, + pub proof: DcApiDecoderProof, } -impl DecodedObservation { +impl DcApiDecodedObservation { /// Validates failed transaction commit semantics and stable identity fields. pub fn validate(&self) -> kb_core::Result<()> { if self.event_key.trim().is_empty() { @@ -295,22 +296,22 @@ impl DecodedObservation { /// Complete explicit result produced by one decoder invocation. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct DecoderExecutionResult { +pub struct DcApiDecoderExecutionResult { /// Terminal decoder status. - pub status: DecoderOutcomeStatus, + pub status: DcApiDecoderOutcomeStatus, /// Optional recognized instruction or discriminator code. pub recognized_entry_code: std::option::Option, /// Decoded observations. - pub observations: std::vec::Vec, + pub observations: std::vec::Vec, /// Structured diagnostics. - pub diagnostics: std::vec::Vec, + pub diagnostics: std::vec::Vec, } -impl DecoderExecutionResult { +impl DcApiDecoderExecutionResult { /// Builds an unsupported result with no false decoded observation. pub fn unsupported(entry_code: std::option::Option) -> Self { return Self { - status: DecoderOutcomeStatus::Unsupported, + status: DcApiDecoderOutcomeStatus::Unsupported, recognized_entry_code: entry_code, observations: std::vec::Vec::new(), diagnostics: std::vec::Vec::new(), @@ -320,7 +321,7 @@ impl DecoderExecutionResult { /// Builds an ignored result. pub fn ignored(entry_code: std::option::Option) -> Self { return Self { - status: DecoderOutcomeStatus::Ignored, + status: DcApiDecoderOutcomeStatus::Ignored, recognized_entry_code: entry_code, observations: std::vec::Vec::new(), diagnostics: std::vec::Vec::new(), @@ -329,17 +330,17 @@ impl DecoderExecutionResult { /// Validates status and observation consistency. pub fn validate(&self) -> kb_core::Result<()> { - if self.status == DecoderOutcomeStatus::Decoded && self.observations.is_empty() { + if self.status == DcApiDecoderOutcomeStatus::Decoded && self.observations.is_empty() { return std::result::Result::Err(kb_core::Error::invalid_state( "decoded status requires at least one observation", )); } - if self.status != DecoderOutcomeStatus::Decoded && !self.observations.is_empty() { + if self.status != DcApiDecoderOutcomeStatus::Decoded && !self.observations.is_empty() { return std::result::Result::Err(kb_core::Error::invalid_state( "non-decoded status must not contain observations", )); } - if self.status == DecoderOutcomeStatus::Failed && self.diagnostics.is_empty() { + if self.status == DcApiDecoderOutcomeStatus::Failed && self.diagnostics.is_empty() { return std::result::Result::Err(kb_core::Error::invalid_state( "failed decoder status requires at least one diagnostic", )); @@ -355,21 +356,24 @@ impl DecoderExecutionResult { } /// Contextual instruction decoder contract used by the common pipeline. -pub trait InstructionDecoder: std::marker::Send + std::marker::Sync { +pub trait DcApiInstructionDecoder: std::marker::Send + std::marker::Sync { /// Returns the stable decoder identity. - fn identity(&self) -> DecoderIdentity; + fn identity(&self) -> DcApiDecoderIdentity; /// Returns every exact Solana surface supported by the decoder. - fn surfaces(&self) -> &'static [DecoderSurface]; + fn surfaces(&self) -> &'static [DcApiDecoderSurface]; /// Returns the machine-readable declared coverage matrix. - fn coverage(&self) -> std::vec::Vec; + fn coverage(&self) -> std::vec::Vec; /// Recognizes one contextual core instruction for deterministic dispatch. - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> DecoderRecognition; + fn recognize(&self, input: &crate::MdCoreInstructionReplayInput) -> DcApiDecoderRecognition; /// Decodes one recognized contextual core instruction. - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> DecoderExecutionResult; + fn decode(&self, input: &crate::MdCoreInstructionReplayInput) -> DcApiDecoderExecutionResult; } /// Returns true when a decoder declares the exact program id. -pub fn decoder_handles_program_id(decoder: &dyn InstructionDecoder, program_id: &str) -> bool { +pub fn decoder_api_decoder_handles_program_id( + decoder: &dyn DcApiInstructionDecoder, + program_id: &str, +) -> bool { for surface in decoder.surfaces() { if surface.program_id == program_id { return true; @@ -379,8 +383,8 @@ pub fn decoder_handles_program_id(decoder: &dyn InstructionDecoder, program_id: } /// Computes a deterministic lowercase SHA-256 hash for one contextual input. -pub fn contextual_input_hash( - input: &crate::CoreInstructionReplayInput, +pub fn decoder_api_decoder_api_contextual_input_hash( + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result { let serialization_result = serde_json::to_value(input); let mut value = match serialization_result { @@ -391,11 +395,11 @@ pub fn contextual_input_hash( ))); }, }; - return crate::deterministic_json_hash(&mut value); + return crate::decoder_api_deterministic_json_hash(&mut value); } /// Computes a deterministic lowercase SHA-256 hash for one JSON value. -pub fn deterministic_json_hash( +pub fn decoder_api_deterministic_json_hash( value: &mut serde_json::Value, ) -> kb_core::Result { sort_json_value(value); @@ -417,8 +421,8 @@ pub fn deterministic_json_hash( } /// Extracts the first eight payload bytes as normalized lowercase hexadecimal when available. -pub fn discriminator_8_hex( - input: &crate::CoreInstructionReplayInput, +pub fn decoder_api_discriminator_8_hex( + input: &crate::MdCoreInstructionReplayInput, ) -> std::option::Option { let payload = match &input.instruction_payload_json { std::option::Option::Some(value) => value, @@ -465,8 +469,8 @@ fn sort_json_value(value: &mut serde_json::Value) { #[cfg(test)] mod tests { - fn replay_input() -> crate::CoreInstructionReplayInput { - let result = crate::CoreInstructionReplayInput::new( + fn replay_input() -> crate::MdCoreInstructionReplayInput { + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -497,8 +501,8 @@ mod tests { #[test] fn contextual_input_hash_is_stable() { - let first = crate::contextual_input_hash(&replay_input()); - let second = crate::contextual_input_hash(&replay_input()); + let first = crate::decoder_api_decoder_api_contextual_input_hash(&replay_input()); + let second = crate::decoder_api_decoder_api_contextual_input_hash(&replay_input()); assert!(first.is_ok()); assert_eq!(first, second); } @@ -514,8 +518,8 @@ mod tests { "payloadJson": {"dataBase64": "CAcGBQQDAgE="}, "payloadHash": "different-payload-hash" }]); - let first_hash = crate::contextual_input_hash(&first); - let second_hash = crate::contextual_input_hash(&second); + let first_hash = crate::decoder_api_decoder_api_contextual_input_hash(&first); + let second_hash = crate::decoder_api_decoder_api_contextual_input_hash(&second); assert!(first_hash.is_ok()); assert!(second_hash.is_ok()); assert_ne!(first_hash, second_hash); @@ -538,26 +542,26 @@ mod tests { #[test] fn discriminator_uses_first_eight_bytes() { - let value = crate::discriminator_8_hex(&replay_input()); + let value = crate::decoder_api_discriminator_8_hex(&replay_input()); assert_eq!(value.as_deref(), std::option::Option::Some("0102030405060708")); } #[test] fn failed_observation_cannot_be_committed() { - let observation = crate::DecodedObservation { + let observation = crate::DcApiDecodedObservation { event_key: "event".to_string(), - event: crate::DecodedProtocolEvent { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(42), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId("program".to_string()), - protocol_code: crate::ProtocolCode("solana".to_string()), - surface_code: crate::SurfaceCode("system_program".to_string()), - event_code: crate::EventCode("system_program.attempt".to_string()), - event_name: crate::EventName("attempt".to_string()), - event_family: crate::EventFamily::Audit, - source_kind: crate::EventSourceKind::Instruction, - confidence: crate::DecoderConfidence::Exact, + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId("program".to_string()), + protocol_code: crate::MdProtocolCode("solana".to_string()), + surface_code: crate::MdSurfaceCode("system_program".to_string()), + event_code: crate::MdEventCode("system_program.attempt".to_string()), + event_name: crate::MdEventName("attempt".to_string()), + event_family: crate::MdEventFamily::Audit, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::Exact, }, payload_json: serde_json::json!({}), transaction_failed: true, @@ -565,9 +569,9 @@ mod tests { serde_json::json!({"InstructionError": [0, "Custom"]}), ), observation_committed: true, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::ExactLayout, - confidence: crate::DecoderConfidence::Exact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::ExactLayout, + confidence: crate::MdDecoderConfidence::Exact, evidence: std::vec!["layout".to_string()], }, }; diff --git a/kb-lib/src/decoder/api/decoder.rs b/kb-lib/src/decoder/api/decoder.rs index 85a1acf..ec4cbd6 100644 --- a/kb-lib/src/decoder/api/decoder.rs +++ b/kb-lib/src/decoder/api/decoder.rs @@ -5,7 +5,7 @@ /// Decoder support level for a program observation. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum DecoderSupport { +pub enum DcApiDecoderSupport { /// The decoder does not support the observation. No, /// The decoder may support the observation after deeper inspection. @@ -15,7 +15,7 @@ pub enum DecoderSupport { } /// Common trait implemented by every protocol decoder crate. -pub trait ProtocolDecoder { +pub trait DcApiProtocolDecoder { /// Returns the stable decoder name. fn decoder_name(&self) -> &'static str; /// Returns the decoder implementation version. @@ -23,7 +23,7 @@ pub trait ProtocolDecoder { /// Returns the Solana program ids handled by this decoder. fn program_ids(&self) -> &'static [&'static str]; /// Checks whether the decoder handles a program id. - fn handles_program_id(&self, program_id: &crate::ProgramId) -> bool { + fn handles_program_id(&self, program_id: &crate::MdProgramId) -> bool { for candidate in self.program_ids() { if program_id.0.as_str() == *candidate { return true; @@ -32,19 +32,22 @@ pub trait ProtocolDecoder { return false; } /// Checks whether the decoder supports a generic program observation. - fn supports_observation(&self, observation: &crate::ProgramObservation) -> DecoderSupport; + fn supports_observation( + &self, + observation: &crate::MdProgramObservation, + ) -> DcApiDecoderSupport; /// Decodes a generic program observation into protocol events. fn decode_observation( &self, - observation: &crate::ProgramObservation, - ) -> kb_core::Result>; + observation: &crate::MdProgramObservation, + ) -> kb_core::Result>; } /// Initial decoder implementation placeholder for API-level tests. #[derive(Clone, Debug, Default)] -pub struct InitialDecoder; +pub struct DcApiInitialDecoder; -impl ProtocolDecoder for InitialDecoder { +impl DcApiProtocolDecoder for DcApiInitialDecoder { fn decoder_name(&self) -> &'static str { return "kb_decoder_api"; } @@ -57,17 +60,20 @@ impl ProtocolDecoder for InitialDecoder { return &[]; } - fn supports_observation(&self, observation: &crate::ProgramObservation) -> DecoderSupport { - if ProtocolDecoder::handles_program_id(self, &observation.program_id) { - return DecoderSupport::Maybe; + fn supports_observation( + &self, + observation: &crate::MdProgramObservation, + ) -> DcApiDecoderSupport { + if DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + return DcApiDecoderSupport::Maybe; } - return DecoderSupport::No; + return DcApiDecoderSupport::No; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } diff --git a/kb-lib/src/decoder/bridge.rs b/kb-lib/src/decoder/bridge.rs index 762d024..1d688ec 100644 --- a/kb-lib/src/decoder/bridge.rs +++ b/kb-lib/src/decoder/bridge.rs @@ -3,7 +3,7 @@ //! `bridge` decoder family. -pub mod circle_cctp_token_messenger_minter; -pub mod circle_cctp_token_messenger_minter_v2; -pub mod layer_zero_endpoint; -pub mod layer_zero_executor; +mod circle_cctp_token_messenger_minter; +mod circle_cctp_token_messenger_minter_v2; +mod layer_zero_endpoint; +mod layer_zero_executor; diff --git a/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter.rs b/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter.rs index 3bd5c51..6ac6abd 100644 --- a/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter.rs +++ b/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_bridge_circle_cctp_token_messenger_minter`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_bridge_circle_cctp_token_messenger_minter"; +const LEGACY_CRATE: &str = "kb_decoder_bridge_circle_cctp_token_messenger_minter"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter_v2.rs b/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter_v2.rs index ad1880a..97ca630 100644 --- a/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter_v2.rs +++ b/kb-lib/src/decoder/bridge/circle_cctp_token_messenger_minter_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_bridge_circle_cctp_token_messenger_minter_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_bridge_circle_cctp_token_messenger_minter_v2"; +const LEGACY_CRATE: &str = "kb_decoder_bridge_circle_cctp_token_messenger_minter_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/bridge/layer_zero_endpoint.rs b/kb-lib/src/decoder/bridge/layer_zero_endpoint.rs index 9482c28..1a2815b 100644 --- a/kb-lib/src/decoder/bridge/layer_zero_endpoint.rs +++ b/kb-lib/src/decoder/bridge/layer_zero_endpoint.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_bridge_layer_zero_endpoint`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_bridge_layer_zero_endpoint"; +const LEGACY_CRATE: &str = "kb_decoder_bridge_layer_zero_endpoint"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/bridge/layer_zero_executor.rs b/kb-lib/src/decoder/bridge/layer_zero_executor.rs index 16a1b6c..59c5f19 100644 --- a/kb-lib/src/decoder/bridge/layer_zero_executor.rs +++ b/kb-lib/src/decoder/bridge/layer_zero_executor.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_bridge_layer_zero_executor`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_bridge_layer_zero_executor"; +const LEGACY_CRATE: &str = "kb_decoder_bridge_layer_zero_executor"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/clmm.rs b/kb-lib/src/decoder/clmm.rs index e9c1013..3052e29 100644 --- a/kb-lib/src/decoder/clmm.rs +++ b/kb-lib/src/decoder/clmm.rs @@ -3,9 +3,9 @@ //! `clmm` decoder family. -pub mod byreal; -pub mod fusion; -pub mod orca_whirlpool; -pub mod pancake_swap; -pub mod raydium; -pub mod stabble; +mod byreal; +mod fusion; +mod orca_whirlpool; +mod pancake_swap; +mod raydium; +mod stabble; diff --git a/kb-lib/src/decoder/clmm/byreal.rs b/kb-lib/src/decoder/clmm/byreal.rs index fcf0022..efddb16 100644 --- a/kb-lib/src/decoder/clmm/byreal.rs +++ b/kb-lib/src/decoder/clmm/byreal.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_clmm_byreal`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_clmm_byreal"; +const LEGACY_CRATE: &str = "kb_decoder_clmm_byreal"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/clmm/fusion.rs b/kb-lib/src/decoder/clmm/fusion.rs index f0e0438..462ed4d 100644 --- a/kb-lib/src/decoder/clmm/fusion.rs +++ b/kb-lib/src/decoder/clmm/fusion.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_clmm_fusion`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_clmm_fusion"; +const LEGACY_CRATE: &str = "kb_decoder_clmm_fusion"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/clmm/orca_whirlpool.rs b/kb-lib/src/decoder/clmm/orca_whirlpool.rs index 52ee4e9..f883d91 100644 --- a/kb-lib/src/decoder/clmm/orca_whirlpool.rs +++ b/kb-lib/src/decoder/clmm/orca_whirlpool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_clmm_orca_whirlpool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_clmm_orca_whirlpool"; +const LEGACY_CRATE: &str = "kb_decoder_clmm_orca_whirlpool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/clmm/pancake_swap.rs b/kb-lib/src/decoder/clmm/pancake_swap.rs index 1652ec2..e5b6747 100644 --- a/kb-lib/src/decoder/clmm/pancake_swap.rs +++ b/kb-lib/src/decoder/clmm/pancake_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_clmm_pancake_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_clmm_pancake_swap"; +const LEGACY_CRATE: &str = "kb_decoder_clmm_pancake_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/clmm/raydium.rs b/kb-lib/src/decoder/clmm/raydium.rs index a5063e6..d430148 100644 --- a/kb-lib/src/decoder/clmm/raydium.rs +++ b/kb-lib/src/decoder/clmm/raydium.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_clmm_raydium`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_clmm_raydium"; +const LEGACY_CRATE: &str = "kb_decoder_clmm_raydium"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/clmm/stabble.rs b/kb-lib/src/decoder/clmm/stabble.rs index 3165488..35aaef1 100644 --- a/kb-lib/src/decoder/clmm/stabble.rs +++ b/kb-lib/src/decoder/clmm/stabble.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_clmm_stabble`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_clmm_stabble"; +const LEGACY_CRATE: &str = "kb_decoder_clmm_stabble"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/cpmm.rs b/kb-lib/src/decoder/cpmm.rs index 1210730..3895c9e 100644 --- a/kb-lib/src/decoder/cpmm.rs +++ b/kb-lib/src/decoder/cpmm.rs @@ -3,4 +3,4 @@ //! `cpmm` decoder family. -pub mod raydium; +mod raydium; diff --git a/kb-lib/src/decoder/cpmm/raydium.rs b/kb-lib/src/decoder/cpmm/raydium.rs index d8b4bc5..fe83f3c 100644 --- a/kb-lib/src/decoder/cpmm/raydium.rs +++ b/kb-lib/src/decoder/cpmm/raydium.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_cpmm_raydium`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_cpmm_raydium"; +const LEGACY_CRATE: &str = "kb_decoder_cpmm_raydium"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/dlmm.rs b/kb-lib/src/decoder/dlmm.rs index 5a5e9cf..b878ca3 100644 --- a/kb-lib/src/decoder/dlmm.rs +++ b/kb-lib/src/decoder/dlmm.rs @@ -3,4 +3,4 @@ //! `dlmm` decoder family. -pub mod meteora; +mod meteora; diff --git a/kb-lib/src/decoder/dlmm/meteora.rs b/kb-lib/src/decoder/dlmm/meteora.rs index e9f251c..73a2b50 100644 --- a/kb-lib/src/decoder/dlmm/meteora.rs +++ b/kb-lib/src/decoder/dlmm/meteora.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_dlmm_meteora`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_dlmm_meteora"; +const LEGACY_CRATE: &str = "kb_decoder_dlmm_meteora"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/fees.rs b/kb-lib/src/decoder/fees.rs index a095265..e99509e 100644 --- a/kb-lib/src/decoder/fees.rs +++ b/kb-lib/src/decoder/fees.rs @@ -3,5 +3,5 @@ //! `fees` decoder family. -pub mod bags_fee_share_v1; -pub mod bags_fee_share_v2; +mod bags_fee_share_v1; +mod bags_fee_share_v2; diff --git a/kb-lib/src/decoder/fees/bags_fee_share_v1.rs b/kb-lib/src/decoder/fees/bags_fee_share_v1.rs index 70ea157..8f1ab4f 100644 --- a/kb-lib/src/decoder/fees/bags_fee_share_v1.rs +++ b/kb-lib/src/decoder/fees/bags_fee_share_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_fees_bags_fee_share_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_fees_bags_fee_share_v1"; +const LEGACY_CRATE: &str = "kb_decoder_fees_bags_fee_share_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/fees/bags_fee_share_v2.rs b/kb-lib/src/decoder/fees/bags_fee_share_v2.rs index eec53f8..a669c83 100644 --- a/kb-lib/src/decoder/fees/bags_fee_share_v2.rs +++ b/kb-lib/src/decoder/fees/bags_fee_share_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_fees_bags_fee_share_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_fees_bags_fee_share_v2"; +const LEGACY_CRATE: &str = "kb_decoder_fees_bags_fee_share_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/governance.rs b/kb-lib/src/decoder/governance.rs index efce434..d0a2e40 100644 --- a/kb-lib/src/decoder/governance.rs +++ b/kb-lib/src/decoder/governance.rs @@ -3,4 +3,4 @@ //! `governance` decoder family. -pub mod metadao_bid_wall; +mod metadao_bid_wall; diff --git a/kb-lib/src/decoder/governance/metadao_bid_wall.rs b/kb-lib/src/decoder/governance/metadao_bid_wall.rs index b8eabe2..c9ea897 100644 --- a/kb-lib/src/decoder/governance/metadao_bid_wall.rs +++ b/kb-lib/src/decoder/governance/metadao_bid_wall.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_governance_metadao_bid_wall`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_governance_metadao_bid_wall"; +const LEGACY_CRATE: &str = "kb_decoder_governance_metadao_bid_wall"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad.rs b/kb-lib/src/decoder/launchpad.rs index 508b611..0c30872 100644 --- a/kb-lib/src/decoder/launchpad.rs +++ b/kb-lib/src/decoder/launchpad.rs @@ -3,12 +3,12 @@ //! `launchpad` decoder family. -pub mod boop_fun; -pub mod metadao_ico; -pub mod meteora_dbc; -pub mod moonit; -pub mod orca_wavebreak; -pub mod printr; -pub mod pump_fun; -pub mod pump_pumpup_ai; -pub mod raydium_launchlab; +mod boop_fun; +mod metadao_ico; +mod meteora_dbc; +mod moonit; +mod orca_wavebreak; +mod printr; +mod pump_fun; +mod pump_pumpup_ai; +mod raydium_launchlab; diff --git a/kb-lib/src/decoder/launchpad/boop_fun.rs b/kb-lib/src/decoder/launchpad/boop_fun.rs index ceb2683..452d8dc 100644 --- a/kb-lib/src/decoder/launchpad/boop_fun.rs +++ b/kb-lib/src/decoder/launchpad/boop_fun.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_boop_fun`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_boop_fun"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_boop_fun"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/metadao_ico.rs b/kb-lib/src/decoder/launchpad/metadao_ico.rs index edc4d37..b954102 100644 --- a/kb-lib/src/decoder/launchpad/metadao_ico.rs +++ b/kb-lib/src/decoder/launchpad/metadao_ico.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_metadao_ico`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_metadao_ico"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_metadao_ico"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/meteora_dbc.rs b/kb-lib/src/decoder/launchpad/meteora_dbc.rs index 920ad2d..1ea5fc1 100644 --- a/kb-lib/src/decoder/launchpad/meteora_dbc.rs +++ b/kb-lib/src/decoder/launchpad/meteora_dbc.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_meteora_dbc`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_meteora_dbc"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_meteora_dbc"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/moonit.rs b/kb-lib/src/decoder/launchpad/moonit.rs index 301a630..1cb1e4d 100644 --- a/kb-lib/src/decoder/launchpad/moonit.rs +++ b/kb-lib/src/decoder/launchpad/moonit.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_moonit`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_moonit"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_moonit"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/orca_wavebreak.rs b/kb-lib/src/decoder/launchpad/orca_wavebreak.rs index 3daea74..2aefc1c 100644 --- a/kb-lib/src/decoder/launchpad/orca_wavebreak.rs +++ b/kb-lib/src/decoder/launchpad/orca_wavebreak.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_orca_wavebreak`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_orca_wavebreak"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_orca_wavebreak"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/printr.rs b/kb-lib/src/decoder/launchpad/printr.rs index 00b719c..c21d092 100644 --- a/kb-lib/src/decoder/launchpad/printr.rs +++ b/kb-lib/src/decoder/launchpad/printr.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_printr`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_printr"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_printr"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/pump_fun.rs b/kb-lib/src/decoder/launchpad/pump_fun.rs index 51282e7..2aa8db6 100644 --- a/kb-lib/src/decoder/launchpad/pump_fun.rs +++ b/kb-lib/src/decoder/launchpad/pump_fun.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_pump_fun`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_pump_fun"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_pump_fun"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/pump_pumpup_ai.rs b/kb-lib/src/decoder/launchpad/pump_pumpup_ai.rs index edf05fa..97e7381 100644 --- a/kb-lib/src/decoder/launchpad/pump_pumpup_ai.rs +++ b/kb-lib/src/decoder/launchpad/pump_pumpup_ai.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_pump_pumpup_ai`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_pump_pumpup_ai"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_pump_pumpup_ai"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/launchpad/raydium_launchlab.rs b/kb-lib/src/decoder/launchpad/raydium_launchlab.rs index 39702b8..a477d45 100644 --- a/kb-lib/src/decoder/launchpad/raydium_launchlab.rs +++ b/kb-lib/src/decoder/launchpad/raydium_launchlab.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_launchpad_raydium_launchlab`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_launchpad_raydium_launchlab"; +const LEGACY_CRATE: &str = "kb_decoder_launchpad_raydium_launchlab"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lending.rs b/kb-lib/src/decoder/lending.rs index f943cd0..e6734b9 100644 --- a/kb-lib/src/decoder/lending.rs +++ b/kb-lib/src/decoder/lending.rs @@ -3,10 +3,10 @@ //! `lending` decoder family. -pub mod clone; -pub mod jupiter_lend_borrow; -pub mod jupiter_lend_earn; -pub mod jupiter_lend_flash_loan; -pub mod jupiter_lend_liquidity; -pub mod kamino; -pub mod marginfi_v2; +mod clone; +mod jupiter_lend_borrow; +mod jupiter_lend_earn; +mod jupiter_lend_flash_loan; +mod jupiter_lend_liquidity; +mod kamino; +mod marginfi_v2; diff --git a/kb-lib/src/decoder/lending/clone.rs b/kb-lib/src/decoder/lending/clone.rs index 88b796b..2dabd03 100644 --- a/kb-lib/src/decoder/lending/clone.rs +++ b/kb-lib/src/decoder/lending/clone.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lending_clone`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lending_clone"; +const LEGACY_CRATE: &str = "kb_decoder_lending_clone"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lending/jupiter_lend_borrow.rs b/kb-lib/src/decoder/lending/jupiter_lend_borrow.rs index 58cf9b7..ee5c08d 100644 --- a/kb-lib/src/decoder/lending/jupiter_lend_borrow.rs +++ b/kb-lib/src/decoder/lending/jupiter_lend_borrow.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lending_jupiter_lend_borrow`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_borrow"; +const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_borrow"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lending/jupiter_lend_earn.rs b/kb-lib/src/decoder/lending/jupiter_lend_earn.rs index 02d5aeb..eec4405 100644 --- a/kb-lib/src/decoder/lending/jupiter_lend_earn.rs +++ b/kb-lib/src/decoder/lending/jupiter_lend_earn.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lending_jupiter_lend_earn`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_earn"; +const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_earn"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lending/jupiter_lend_flash_loan.rs b/kb-lib/src/decoder/lending/jupiter_lend_flash_loan.rs index 2cce758..b5df193 100644 --- a/kb-lib/src/decoder/lending/jupiter_lend_flash_loan.rs +++ b/kb-lib/src/decoder/lending/jupiter_lend_flash_loan.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lending_jupiter_lend_flash_loan`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_flash_loan"; +const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_flash_loan"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lending/jupiter_lend_liquidity.rs b/kb-lib/src/decoder/lending/jupiter_lend_liquidity.rs index 56f13c6..f4bf409 100644 --- a/kb-lib/src/decoder/lending/jupiter_lend_liquidity.rs +++ b/kb-lib/src/decoder/lending/jupiter_lend_liquidity.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lending_jupiter_lend_liquidity`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_liquidity"; +const LEGACY_CRATE: &str = "kb_decoder_lending_jupiter_lend_liquidity"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lending/kamino.rs b/kb-lib/src/decoder/lending/kamino.rs index cf79836..6635f29 100644 --- a/kb-lib/src/decoder/lending/kamino.rs +++ b/kb-lib/src/decoder/lending/kamino.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lending_kamino`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lending_kamino"; +const LEGACY_CRATE: &str = "kb_decoder_lending_kamino"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lending/marginfi_v2.rs b/kb-lib/src/decoder/lending/marginfi_v2.rs index ef173b9..2cd4ee2 100644 --- a/kb-lib/src/decoder/lending/marginfi_v2.rs +++ b/kb-lib/src/decoder/lending/marginfi_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lending_marginfi_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lending_marginfi_v2"; +const LEGACY_CRATE: &str = "kb_decoder_lending_marginfi_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/lock.rs b/kb-lib/src/decoder/lock.rs index 4e47726..160fc6c 100644 --- a/kb-lib/src/decoder/lock.rs +++ b/kb-lib/src/decoder/lock.rs @@ -3,4 +3,4 @@ //! `lock` decoder family. -pub mod raydium_lp; +mod raydium_lp; diff --git a/kb-lib/src/decoder/lock/raydium_lp.rs b/kb-lib/src/decoder/lock/raydium_lp.rs index 0b387d4..15be905 100644 --- a/kb-lib/src/decoder/lock/raydium_lp.rs +++ b/kb-lib/src/decoder/lock/raydium_lp.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_lock_raydium_lp`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_lock_raydium_lp"; +const LEGACY_CRATE: &str = "kb_decoder_lock_raydium_lp"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/metadata.rs b/kb-lib/src/decoder/metadata.rs index dfbd5af..8270576 100644 --- a/kb-lib/src/decoder/metadata.rs +++ b/kb-lib/src/decoder/metadata.rs @@ -3,8 +3,216 @@ //! `metadata` decoder family. -pub mod metaplex_token_metadata; -pub mod spl_name_service; +mod metaplex_token_metadata; +mod spl_name_service; +/// Approve Collection Authority discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR; +/// Approve Use Authority discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR; +/// Bubblegum Set Collection Size discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR; +/// Burn discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_BURN_DISCRIMINATOR; +/// Historical Burn Edition NFT discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR; +/// Historical Burn NFT discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR; +/// Close Accounts discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR; +/// Close Escrow Account discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR; +/// Collect discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_COLLECT_DISCRIMINATOR; +/// Convert Master Edition V1 to V2 discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR; +/// Modern Create discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CREATE_DISCRIMINATOR; +/// Create Escrow Account discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR; +/// Historical Create Master Edition discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR; +/// Create Master Edition V3 discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR; +/// Historical Create Metadata Account discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR; +/// Historical Create Metadata Account V2 discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +/// Create Metadata Account V3 discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR; +/// Delegate discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DELEGATE_DISCRIMINATOR; +/// Deprecated Create Master Edition discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR; +/// Deprecated Create Reservation List discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR; +/// Deprecated printing-token mint-new-edition discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR; +/// Deprecated Mint Printing Tokens discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR; +/// Deprecated Mint Printing Tokens Via Token discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR; +/// Deprecated Set Reservation List discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR; +/// Number of bytes retained in malformed-wire diagnostics. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_DIAGNOSTIC_PREFIX_BYTES; +/// Stable event payload contract version. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_EVENT_VERSION; +/// Freeze Delegated Account discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR; +/// Current pre-release instruction inventory. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_INSTRUCTION_ENTRIES; +/// Lock discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_LOCK_DISCRIMINATOR; +/// Maximum encoded base64 instruction payload size. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_MAX_BASE64_BYTES; +/// Maximum number of instruction accounts accepted by this decoder. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_MAX_INSTRUCTION_ACCOUNTS; +/// Tracing target for this decoder. +/// Maximum retained instruction payload size. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_MAX_INSTRUCTION_BYTES; +/// Migrate discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_MIGRATE_DISCRIMINATOR; +/// Modern Mint discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_MINT_DISCRIMINATOR; +/// Mint New Edition From Master Edition Via Token discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR; +/// Mint New Edition From Master Edition Via Vault Proxy discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR; +/// Modern Print discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_PRINT_DISCRIMINATOR; +/// Puff Metadata discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR; +/// Remove Creator Verification discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR; +/// Resize discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_RESIZE_DISCRIMINATOR; +/// Revoke Collection Authority discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR; +/// Revoke discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_REVOKE_DISCRIMINATOR; +/// Revoke Use Authority discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR; +/// Set And Verify Collection discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR; +/// Set And Verify Sized Collection Item discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +/// Set Collection Size discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR; +/// Set Token Standard discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR; +/// Sign Metadata discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR; +/// Stable decoder surface code. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_SURFACE_CODE; +/// Thaw Delegated Account discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR; +/// Canonical tracing target for this crate. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_TRACING_TARGET; +/// Transfer discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_TRANSFER_DISCRIMINATOR; +/// Transfer Out Of Escrow discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR; +/// Unlock discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UNLOCK_DISCRIMINATOR; +/// Unverify Collection discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR; +/// Modern Unverify discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR; +/// Unverify Sized Collection Item discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +/// Modern Update discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UPDATE_DISCRIMINATOR; +/// Historical Update Metadata Account discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR; +/// Update Metadata Account V2 discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +/// Update Primary Sale Happened Via Token discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR; +/// Modern Use discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_USE_DISCRIMINATOR; +/// Utilize discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_UTILIZE_DISCRIMINATOR; +/// Verify Collection discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR; +/// Modern Verify discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_VERIFY_DISCRIMINATOR; +/// Verify Sized Collection Item discriminator. +pub(crate) use self::metaplex_token_metadata::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +/// Crate-root access to `decode` from `instruction`. +pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode; +/// Crate-root access to `entry_for_discriminator` from `instruction`. +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; + +/// Exhaustive published Metaplex account-key inventory. +pub use self::metaplex_token_metadata::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT; /// Exact decoder for the Metaplex Token Metadata program. -pub use self::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; +pub use self::metaplex_token_metadata::DcMetadataMetaplexTokenMetadataDecoder; +/// Canonical projection shared by Collection and Use Authority records. +pub use self::metaplex_token_metadata::DcMetadataMtmAuthorityRecordAccountSnapshot; +/// Stable identity and policy of one canonical account snapshot. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalAccountIdentity; +/// Lifecycle class of one canonical account layout. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalAccountLifecycle; +/// Provenance retained for one canonical account observation. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalAccountProvenance; +/// Execution policy separated from historical materialization. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalExecutionPolicy; +/// Materialization policy for active or historical state. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalMaterializationPolicy; +/// Canonical account envelope used by materializers and replay. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalMetadataAccountSnapshot; +/// Typed canonical Metaplex account state. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalMetadataAccountState; +/// Origin of one canonical account observation. +pub use self::metaplex_token_metadata::DcMetadataMtmCanonicalObservationSource; +/// Canonical projection shared by Metadata and Holder delegate records. +pub use self::metaplex_token_metadata::DcMetadataMtmDelegateRecordAccountSnapshot; +/// Supported edition account layout. +pub use self::metaplex_token_metadata::DcMetadataMtmEditionAccountKind; +/// Canonical bounded projection of one edition or master-edition account. +pub use self::metaplex_token_metadata::DcMetadataMtmEditionAccountSnapshot; +/// Supported Edition Marker account layout. +pub use self::metaplex_token_metadata::DcMetadataMtmEditionMarkerAccountKind; +/// Canonical bounded projection of one Edition Marker account. +pub use self::metaplex_token_metadata::DcMetadataMtmEditionMarkerAccountSnapshot; +/// Bounded error returned while decoding a Metadata account. +pub use self::metaplex_token_metadata::DcMetadataMtmMetadataAccountDecodeError; +/// One entry in the exhaustive published account-key audit. +pub use self::metaplex_token_metadata::DcMetadataMtmMetadataAccountLayoutAuditEntry; +/// Canonical bounded projection of one Metadata account. +pub use self::metaplex_token_metadata::DcMetadataMtmMetadataAccountSnapshot; +/// One bounded historical reservation entry. +pub use self::metaplex_token_metadata::DcMetadataMtmReservationEntrySnapshot; +/// Historical Reservation List account generation. +pub use self::metaplex_token_metadata::DcMetadataMtmReservationListAccountKind; +/// Canonical decode-only projection of a historical Reservation List account. +pub use self::metaplex_token_metadata::DcMetadataMtmReservationListAccountSnapshot; +/// Canonical projection of one Token Owned Escrow account. +pub use self::metaplex_token_metadata::DcMetadataMtmTokenOwnedEscrowAccountSnapshot; +/// Authority form used by one Token Owned Escrow account. +pub use self::metaplex_token_metadata::DcMetadataMtmTokenOwnedEscrowAuthorityKind; +/// Canonical bounded projection of one programmable Token Record account. +pub use self::metaplex_token_metadata::DcMetadataMtmTokenRecordAccountSnapshot; +/// Decodes one Collection Authority Record account. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_collection_authority_record_account; +/// Decodes and validates one edition or master-edition account snapshot. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_edition_account; +/// Decodes and validates one Edition Marker account snapshot. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account; +/// Decodes one Holder Delegate Record account. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_holder_delegate_record_account; +/// Decodes and validates one canonical Metadata account snapshot. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_metadata_account; +/// Decodes one Metadata Delegate Record account. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_metadata_delegate_record_account; +/// Decodes one historical Reservation List V1 or V2 account. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account; +/// Decodes one Token Owned Escrow account. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account; +/// Decodes and validates one programmable Token Record account snapshot. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_token_record_account; +/// Decodes one Use Authority Record account. +pub use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account; diff --git a/kb-lib/src/decoder/metadata/metaplex_token_metadata.rs b/kb-lib/src/decoder/metadata/metaplex_token_metadata.rs index acdc764..136668b 100644 --- a/kb-lib/src/decoder/metadata/metaplex_token_metadata.rs +++ b/kb-lib/src/decoder/metadata/metaplex_token_metadata.rs @@ -10,214 +10,212 @@ mod decoder; mod instruction; /// Approve Collection Authority discriminator. -pub(crate) use self::constants::APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR; /// Approve Use Authority discriminator. -pub(crate) use self::constants::APPROVE_USE_AUTHORITY_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR; /// Bubblegum Set Collection Size discriminator. -pub(crate) use self::constants::BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR; /// Burn discriminator. -pub(crate) use self::constants::BURN_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_BURN_DISCRIMINATOR; /// Historical Burn Edition NFT discriminator. -pub(crate) use self::constants::BURN_EDITION_NFT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR; /// Historical Burn NFT discriminator. -pub(crate) use self::constants::BURN_NFT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR; /// Close Accounts discriminator. -pub(crate) use self::constants::CLOSE_ACCOUNTS_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR; /// Close Escrow Account discriminator. -pub(crate) use self::constants::CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR; /// Collect discriminator. -pub(crate) use self::constants::COLLECT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_COLLECT_DISCRIMINATOR; /// Convert Master Edition V1 to V2 discriminator. -pub(crate) use self::constants::CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR; /// Modern Create discriminator. -pub(crate) use self::constants::CREATE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CREATE_DISCRIMINATOR; /// Create Escrow Account discriminator. -pub(crate) use self::constants::CREATE_ESCROW_ACCOUNT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR; /// Historical Create Master Edition discriminator. -pub(crate) use self::constants::CREATE_MASTER_EDITION_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR; /// Create Master Edition V3 discriminator. -pub(crate) use self::constants::CREATE_MASTER_EDITION_V3_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR; /// Historical Create Metadata Account discriminator. -pub(crate) use self::constants::CREATE_METADATA_ACCOUNT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR; /// Historical Create Metadata Account V2 discriminator. -pub(crate) use self::constants::CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; /// Create Metadata Account V3 discriminator. -pub(crate) use self::constants::CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR; /// Delegate discriminator. -pub(crate) use self::constants::DELEGATE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_DELEGATE_DISCRIMINATOR; /// Deprecated Create Master Edition discriminator. -pub(crate) use self::constants::DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR; /// Deprecated Create Reservation List discriminator. -pub(crate) use self::constants::DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR; /// Deprecated printing-token mint-new-edition discriminator. -pub(crate) use self::constants::DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR; /// Deprecated Mint Printing Tokens discriminator. -pub(crate) use self::constants::DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR; /// Deprecated Mint Printing Tokens Via Token discriminator. -pub(crate) use self::constants::DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR; /// Deprecated Set Reservation List discriminator. -pub(crate) use self::constants::DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR; /// Number of bytes retained in malformed-wire diagnostics. -pub(crate) use self::constants::DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::constants::DC_METADATA_MTM_DIAGNOSTIC_PREFIX_BYTES; /// Stable event payload contract version. -pub(crate) use self::constants::EVENT_VERSION; +pub(crate) use self::constants::DC_METADATA_MTM_EVENT_VERSION; /// Freeze Delegated Account discriminator. -pub(crate) use self::constants::FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR; /// Current pre-release instruction inventory. -pub(crate) use self::constants::INSTRUCTION_ENTRIES; +pub(crate) use self::constants::DC_METADATA_MTM_INSTRUCTION_ENTRIES; /// Lock discriminator. -pub(crate) use self::constants::LOCK_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_LOCK_DISCRIMINATOR; /// Maximum encoded base64 instruction payload size. -pub(crate) use self::constants::MAX_BASE64_BYTES; +pub(crate) use self::constants::DC_METADATA_MTM_MAX_BASE64_BYTES; /// Maximum number of instruction accounts accepted by this decoder. -pub(crate) use self::constants::MAX_INSTRUCTION_ACCOUNTS; +pub(crate) use self::constants::DC_METADATA_MTM_MAX_INSTRUCTION_ACCOUNTS; /// Tracing target for this decoder. /// Maximum retained instruction payload size. -pub(crate) use self::constants::MAX_INSTRUCTION_BYTES; +pub(crate) use self::constants::DC_METADATA_MTM_MAX_INSTRUCTION_BYTES; /// Migrate discriminator. -pub(crate) use self::constants::MIGRATE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_MIGRATE_DISCRIMINATOR; /// Modern Mint discriminator. -pub(crate) use self::constants::MINT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_MINT_DISCRIMINATOR; /// Mint New Edition From Master Edition Via Token discriminator. -pub(crate) use self::constants::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR; /// Mint New Edition From Master Edition Via Vault Proxy discriminator. -pub(crate) use self::constants::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR; /// Modern Print discriminator. -pub(crate) use self::constants::PRINT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_PRINT_DISCRIMINATOR; /// Puff Metadata discriminator. -pub(crate) use self::constants::PUFF_METADATA_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR; /// Remove Creator Verification discriminator. -pub(crate) use self::constants::REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR; /// Resize discriminator. -pub(crate) use self::constants::RESIZE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_RESIZE_DISCRIMINATOR; /// Revoke Collection Authority discriminator. -pub(crate) use self::constants::REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR; /// Revoke discriminator. -pub(crate) use self::constants::REVOKE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_REVOKE_DISCRIMINATOR; /// Revoke Use Authority discriminator. -pub(crate) use self::constants::REVOKE_USE_AUTHORITY_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR; /// Set And Verify Collection discriminator. -pub(crate) use self::constants::SET_AND_VERIFY_COLLECTION_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR; /// Set And Verify Sized Collection Item discriminator. -pub(crate) use self::constants::SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; /// Set Collection Size discriminator. -pub(crate) use self::constants::SET_COLLECTION_SIZE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR; /// Set Token Standard discriminator. -pub(crate) use self::constants::SET_TOKEN_STANDARD_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR; /// Sign Metadata discriminator. -pub(crate) use self::constants::SIGN_METADATA_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR; /// Stable decoder surface code. -pub(crate) use self::constants::SURFACE_CODE; +pub(crate) use self::constants::DC_METADATA_MTM_SURFACE_CODE; /// Thaw Delegated Account discriminator. -pub(crate) use self::constants::THAW_DELEGATED_ACCOUNT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR; /// Canonical tracing target for this crate. -pub(crate) use self::constants::TRACING_TARGET; +pub(crate) use self::constants::DC_METADATA_MTM_TRACING_TARGET; /// Transfer discriminator. -pub(crate) use self::constants::TRANSFER_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_TRANSFER_DISCRIMINATOR; /// Transfer Out Of Escrow discriminator. -pub(crate) use self::constants::TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR; /// Unlock discriminator. -pub(crate) use self::constants::UNLOCK_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UNLOCK_DISCRIMINATOR; /// Unverify Collection discriminator. -pub(crate) use self::constants::UNVERIFY_COLLECTION_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR; /// Modern Unverify discriminator. -pub(crate) use self::constants::UNVERIFY_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR; /// Unverify Sized Collection Item discriminator. -pub(crate) use self::constants::UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; /// Modern Update discriminator. -pub(crate) use self::constants::UPDATE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UPDATE_DISCRIMINATOR; /// Historical Update Metadata Account discriminator. -pub(crate) use self::constants::UPDATE_METADATA_ACCOUNT_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR; /// Update Metadata Account V2 discriminator. -pub(crate) use self::constants::UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; /// Update Primary Sale Happened Via Token discriminator. -pub(crate) use self::constants::UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR; /// Modern Use discriminator. -pub(crate) use self::constants::USE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_USE_DISCRIMINATOR; /// Utilize discriminator. -pub(crate) use self::constants::UTILIZE_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_UTILIZE_DISCRIMINATOR; /// Verify Collection discriminator. -pub(crate) use self::constants::VERIFY_COLLECTION_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR; /// Modern Verify discriminator. -pub(crate) use self::constants::VERIFY_DISCRIMINATOR; +pub(crate) use self::constants::DC_METADATA_MTM_VERIFY_DISCRIMINATOR; /// Verify Sized Collection Item discriminator. -pub(crate) use self::constants::VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; -/// Crate-root access to `ParsedInstruction` from `instruction`. -pub(crate) use self::instruction::ParsedInstruction; +pub(crate) use self::constants::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; /// Crate-root access to `decode` from `instruction`. -pub(crate) use self::instruction::decode; +pub(crate) use self::instruction::decoder_metadata_metaplex_token_metadata_decode; /// Crate-root access to `entry_for_discriminator` from `instruction`. -pub(crate) use self::instruction::entry_for_discriminator; +pub(crate) use self::instruction::decoder_metadata_metaplex_token_metadata_entry_for_discriminator; /// Crate-root access to `payload_discriminator` from `instruction`. -pub(crate) use self::instruction::payload_discriminator; +pub(crate) use self::instruction::decoder_metadata_metaplex_token_metadata_payload_discriminator; -/// Canonical projection shared by Collection and Use Authority records. -pub use self::account::AuthorityRecordAccountSnapshot; -/// Canonical projection shared by Metadata and Holder delegate records. -pub use self::account::DelegateRecordAccountSnapshot; -/// Supported edition account layout. -pub use self::account::EditionAccountKind; -/// Canonical bounded projection of one edition or master-edition account. -pub use self::account::EditionAccountSnapshot; -/// Supported Edition Marker account layout. -pub use self::account::EditionMarkerAccountKind; -/// Canonical bounded projection of one Edition Marker account. -pub use self::account::EditionMarkerAccountSnapshot; /// Exhaustive published Metaplex account-key inventory. -pub use self::account::METADATA_ACCOUNT_LAYOUT_AUDIT; +pub use self::account::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT; +/// Canonical projection shared by Collection and Use Authority records. +pub use self::account::DcMetadataMtmAuthorityRecordAccountSnapshot; +/// Canonical projection shared by Metadata and Holder delegate records. +pub use self::account::DcMetadataMtmDelegateRecordAccountSnapshot; +/// Supported edition account layout. +pub use self::account::DcMetadataMtmEditionAccountKind; +/// Canonical bounded projection of one edition or master-edition account. +pub use self::account::DcMetadataMtmEditionAccountSnapshot; +/// Supported Edition Marker account layout. +pub use self::account::DcMetadataMtmEditionMarkerAccountKind; +/// Canonical bounded projection of one Edition Marker account. +pub use self::account::DcMetadataMtmEditionMarkerAccountSnapshot; /// Bounded error returned while decoding a Metadata account. -pub use self::account::MetadataAccountDecodeError; +pub use self::account::DcMetadataMtmMetadataAccountDecodeError; /// One entry in the exhaustive published account-key audit. -pub use self::account::MetadataAccountLayoutAuditEntry; +pub use self::account::DcMetadataMtmMetadataAccountLayoutAuditEntry; /// Canonical bounded projection of one Metadata account. -pub use self::account::MetadataAccountSnapshot; +pub use self::account::DcMetadataMtmMetadataAccountSnapshot; /// One bounded historical reservation entry. -pub use self::account::ReservationEntrySnapshot; +pub use self::account::DcMetadataMtmReservationEntrySnapshot; /// Historical Reservation List account generation. -pub use self::account::ReservationListAccountKind; +pub use self::account::DcMetadataMtmReservationListAccountKind; /// Canonical decode-only projection of a historical Reservation List account. -pub use self::account::ReservationListAccountSnapshot; +pub use self::account::DcMetadataMtmReservationListAccountSnapshot; /// Canonical projection of one Token Owned Escrow account. -pub use self::account::TokenOwnedEscrowAccountSnapshot; +pub use self::account::DcMetadataMtmTokenOwnedEscrowAccountSnapshot; /// Authority form used by one Token Owned Escrow account. -pub use self::account::TokenOwnedEscrowAuthorityKind; +pub use self::account::DcMetadataMtmTokenOwnedEscrowAuthorityKind; /// Canonical bounded projection of one programmable Token Record account. -pub use self::account::TokenRecordAccountSnapshot; +pub use self::account::DcMetadataMtmTokenRecordAccountSnapshot; /// Decodes one Collection Authority Record account. -pub use self::account::decode_collection_authority_record_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_collection_authority_record_account; /// Decodes and validates one edition or master-edition account snapshot. -pub use self::account::decode_edition_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_edition_account; /// Decodes and validates one Edition Marker account snapshot. -pub use self::account::decode_edition_marker_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account; /// Decodes one Holder Delegate Record account. -pub use self::account::decode_holder_delegate_record_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_holder_delegate_record_account; /// Decodes and validates one canonical Metadata account snapshot. -pub use self::account::decode_metadata_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_metadata_account; /// Decodes one Metadata Delegate Record account. -pub use self::account::decode_metadata_delegate_record_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_metadata_delegate_record_account; /// Decodes one historical Reservation List V1 or V2 account. -pub use self::account::decode_reservation_list_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account; /// Decodes one Token Owned Escrow account. -pub use self::account::decode_token_owned_escrow_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account; /// Decodes and validates one programmable Token Record account snapshot. -pub use self::account::decode_token_record_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_token_record_account; /// Decodes one Use Authority Record account. -pub use self::account::decode_use_authority_record_account; +pub use self::account::decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account; /// Stable identity and policy of one canonical account snapshot. -pub use self::canonical::CanonicalAccountIdentity; +pub use self::canonical::DcMetadataMtmCanonicalAccountIdentity; /// Lifecycle class of one canonical account layout. -pub use self::canonical::CanonicalAccountLifecycle; +pub use self::canonical::DcMetadataMtmCanonicalAccountLifecycle; /// Provenance retained for one canonical account observation. -pub use self::canonical::CanonicalAccountProvenance; +pub use self::canonical::DcMetadataMtmCanonicalAccountProvenance; /// Execution policy separated from historical materialization. -pub use self::canonical::CanonicalExecutionPolicy; +pub use self::canonical::DcMetadataMtmCanonicalExecutionPolicy; /// Materialization policy for active or historical state. -pub use self::canonical::CanonicalMaterializationPolicy; +pub use self::canonical::DcMetadataMtmCanonicalMaterializationPolicy; /// Canonical account envelope used by materializers and replay. -pub use self::canonical::CanonicalMetadataAccountSnapshot; +pub use self::canonical::DcMetadataMtmCanonicalMetadataAccountSnapshot; /// Typed canonical Metaplex account state. -pub use self::canonical::CanonicalMetadataAccountState; +pub use self::canonical::DcMetadataMtmCanonicalMetadataAccountState; /// Origin of one canonical account observation. -pub use self::canonical::CanonicalObservationSource; +pub use self::canonical::DcMetadataMtmCanonicalObservationSource; /// Exact Metaplex Token Metadata decoder. -pub use self::decoder::MetadataMetaplexTokenMetadataDecoder; +pub use self::decoder::DcMetadataMetaplexTokenMetadataDecoder; diff --git a/kb-lib/src/decoder/metadata/metaplex_token_metadata/account.rs b/kb-lib/src/decoder/metadata/metaplex_token_metadata/account.rs index ffc6854..29f8807 100644 --- a/kb-lib/src/decoder/metadata/metaplex_token_metadata/account.rs +++ b/kb-lib/src/decoder/metadata/metaplex_token_metadata/account.rs @@ -1,5 +1,5 @@ // file: kb-lib/src/decoder/metadata/metaplex_token_metadata/account.rs -// version: 11 +// version: 12 //! Bounded decoding and PDA validation for Metaplex Token Metadata accounts. @@ -13,7 +13,7 @@ const MAX_EDITION_MARKER_V2_LEDGER_BYTES: usize = 1_048_576; /// Bounded error returned while decoding a Metadata account. #[derive(Clone, Debug, Eq, PartialEq)] -pub enum MetadataAccountDecodeError { +pub enum DcMetadataMtmMetadataAccountDecodeError { /// The account key is not a valid Solana public key. InvalidAccountKey, /// The account owner is not a valid Solana public key. @@ -56,7 +56,7 @@ pub enum MetadataAccountDecodeError { ProjectionFailed, } -impl std::fmt::Display for MetadataAccountDecodeError { +impl std::fmt::Display for DcMetadataMtmMetadataAccountDecodeError { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let message = match self { Self::InvalidAccountKey => "metadata account key is invalid", @@ -90,11 +90,11 @@ impl std::fmt::Display for MetadataAccountDecodeError { } } -impl std::error::Error for MetadataAccountDecodeError {} +impl std::error::Error for DcMetadataMtmMetadataAccountDecodeError {} /// One audited Metaplex account-key layout. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct MetadataAccountLayoutAuditEntry { +pub struct DcMetadataMtmMetadataAccountLayoutAuditEntry { /// Published `Key` variant name. pub key_name: &'static str, /// Exact Borsh discriminant byte. @@ -106,92 +106,93 @@ pub struct MetadataAccountLayoutAuditEntry { } /// Exhaustive inventory of every published Metaplex Token Metadata `Key` variant. -pub const METADATA_ACCOUNT_LAYOUT_AUDIT: &[MetadataAccountLayoutAuditEntry] = &[ - MetadataAccountLayoutAuditEntry { +pub const DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT: + &[DcMetadataMtmMetadataAccountLayoutAuditEntry] = &[ + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "Uninitialized", discriminant: 0, decoder: "reject_uninitialized", lifecycle: "sentinel", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "EditionV1", discriminant: 1, decoder: "decode_edition_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "MasterEditionV1", discriminant: 2, decoder: "decode_edition_account", lifecycle: "historical_materializable", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "ReservationListV1", discriminant: 3, decoder: "decode_reservation_list_account", lifecycle: "historical_materializable", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "MetadataV1", discriminant: 4, decoder: "decode_metadata_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "ReservationListV2", discriminant: 5, decoder: "decode_reservation_list_account", lifecycle: "historical_materializable", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "MasterEditionV2", discriminant: 6, decoder: "decode_edition_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "EditionMarker", discriminant: 7, decoder: "decode_edition_marker_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "UseAuthorityRecord", discriminant: 8, decoder: "decode_use_authority_record_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "CollectionAuthorityRecord", discriminant: 9, decoder: "decode_collection_authority_record_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "TokenOwnedEscrow", discriminant: 10, decoder: "decode_token_owned_escrow_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "TokenRecord", discriminant: 11, decoder: "decode_token_record_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "MetadataDelegate", discriminant: 12, decoder: "decode_metadata_delegate_record_account", lifecycle: "active", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "EditionMarkerV2", discriminant: 13, decoder: "decode_edition_marker_account", lifecycle: "active_experimental", }, - MetadataAccountLayoutAuditEntry { + DcMetadataMtmMetadataAccountLayoutAuditEntry { key_name: "HolderDelegate", discriminant: 14, decoder: "decode_holder_delegate_record_account", @@ -201,7 +202,7 @@ pub const METADATA_ACCOUNT_LAYOUT_AUDIT: &[MetadataAccountLayoutAuditEntry] = &[ /// Canonical bounded projection of one Metadata account. #[derive(Clone, Debug, PartialEq)] -pub struct MetadataAccountSnapshot { +pub struct DcMetadataMtmMetadataAccountSnapshot { /// Canonical account address. pub account: String, /// Canonical Metadata PDA bump. @@ -227,21 +228,26 @@ pub struct MetadataAccountSnapshot { } /// Decodes one Metadata account after validating owner, bounds and canonical PDA. -pub fn decode_metadata_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_metadata_account( account: &str, owner: &str, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmMetadataAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let account_key = match ::from_str(account) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let owner_key = match ::from_str(owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; let expected_owner = match ::from_str( @@ -249,48 +255,62 @@ pub fn decode_metadata_account( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; if owner_key != expected_owner { - return std::result::Result::Err(MetadataAccountDecodeError::ForeignOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::ForeignOwner); } if data.is_empty() || data.len() > MAX_METADATA_ACCOUNT_BYTES { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let metadata = match mpl_token_metadata::accounts::Metadata::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if metadata.key != mpl_token_metadata::types::Key::MetadataV1 { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataKey, + ); } let name = metadata.name.trim_end_matches('\0').to_string(); let symbol = metadata.symbol.trim_end_matches('\0').to_string(); let uri = metadata.uri.trim_end_matches('\0').to_string(); if name.len() > MAX_NAME_BYTES || symbol.len() > MAX_SYMBOL_BYTES || uri.len() > MAX_URI_BYTES { - return std::result::Result::Err(MetadataAccountDecodeError::MetadataBoundsExceeded); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::MetadataBoundsExceeded, + ); } if metadata .creators .as_ref() .is_some_and(|creators| return creators.len() > MAX_CREATORS) { - return std::result::Result::Err(MetadataAccountDecodeError::MetadataBoundsExceeded); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::MetadataBoundsExceeded, + ); } let (expected_pda, bump) = mpl_token_metadata::accounts::Metadata::find_pda(&metadata.mint); if account_key.to_string() != expected_pda.to_string() { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataPda, + ); } let payload_json = match serde_json::to_value(&metadata) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(MetadataAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmMetadataAccountSnapshot { account: account_key.to_string(), bump, mint: metadata.mint.to_string(), @@ -307,7 +327,7 @@ pub fn decode_metadata_account( /// Supported edition account layout. #[derive(Clone, Debug, Eq, PartialEq)] -pub enum EditionAccountKind { +pub enum DcMetadataMtmEditionAccountKind { /// Historical Master Edition V1 layout. MasterEditionV1, /// Current Master Edition V2 layout. @@ -318,7 +338,7 @@ pub enum EditionAccountKind { /// Canonical bounded projection of one edition or master-edition account. #[derive(Clone, Debug, PartialEq)] -pub struct EditionAccountSnapshot { +pub struct DcMetadataMtmEditionAccountSnapshot { /// Canonical account address. pub account: String, /// Canonical edition PDA bump. @@ -326,7 +346,7 @@ pub struct EditionAccountSnapshot { /// Mint used to derive the edition PDA. pub mint: String, /// Decoded account layout. - pub kind: EditionAccountKind, + pub kind: DcMetadataMtmEditionAccountKind, /// Current printed supply for a master edition. pub supply: std::option::Option, /// Optional maximum supply for a master edition. @@ -344,22 +364,25 @@ pub struct EditionAccountSnapshot { } /// Decodes one MasterEditionV1, MasterEditionV2 or Edition account with exact owner and PDA validation. -pub fn decode_edition_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_edition_account( account: &str, owner: &str, mint: &str, data: &[u8], -) -> std::result::Result { +) -> std::result::Result +{ let account_key = match ::from_str(account) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let owner_key = match ::from_str(owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; let expected_owner = match ::from_str( @@ -367,25 +390,31 @@ pub fn decode_edition_account( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; if owner_key != expected_owner { - return std::result::Result::Err(MetadataAccountDecodeError::ForeignOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::ForeignOwner); } if data.is_empty() || data.len() > 128 { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let (expected_pda, bump) = match mint.parse() { std::result::Result::Ok(mint_key) => { mpl_token_metadata::accounts::MasterEdition::find_pda(&mint_key) }, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; if account_key.to_string() != expected_pda.to_string() { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataPda, + ); } let key = data[0]; if key == mpl_token_metadata::types::Key::MasterEditionV1 as u8 { @@ -393,20 +422,24 @@ pub fn decode_edition_account( { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(EditionAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmEditionAccountSnapshot { account: account_key.to_string(), bump, mint: mint.to_string(), - kind: EditionAccountKind::MasterEditionV1, + kind: DcMetadataMtmEditionAccountKind::MasterEditionV1, supply: std::option::Option::Some(value.supply), max_supply: value.max_supply, parent: std::option::Option::None, @@ -422,20 +455,24 @@ pub fn decode_edition_account( let value = match mpl_token_metadata::accounts::MasterEdition::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(EditionAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmEditionAccountSnapshot { account: account_key.to_string(), bump, mint: mint.to_string(), - kind: EditionAccountKind::MasterEditionV2, + kind: DcMetadataMtmEditionAccountKind::MasterEditionV2, supply: std::option::Option::Some(value.supply), max_supply: value.max_supply, parent: std::option::Option::None, @@ -447,25 +484,31 @@ pub fn decode_edition_account( } if key == mpl_token_metadata::types::Key::EditionV1 as u8 { if data.len() != mpl_token_metadata::accounts::Edition::LEN { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let value = match mpl_token_metadata::accounts::Edition::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(EditionAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmEditionAccountSnapshot { account: account_key.to_string(), bump, mint: mint.to_string(), - kind: EditionAccountKind::EditionV1, + kind: DcMetadataMtmEditionAccountKind::EditionV1, supply: std::option::Option::None, max_supply: std::option::Option::None, parent: std::option::Option::Some(value.parent.to_string()), @@ -475,12 +518,12 @@ pub fn decode_edition_account( payload_json, }); } - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataKey); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataKey); } /// Supported Edition Marker account layout. #[derive(Clone, Debug, Eq, PartialEq)] -pub enum EditionMarkerAccountKind { +pub enum DcMetadataMtmEditionMarkerAccountKind { /// Fixed 248-edition historical/current marker layout. EditionMarkerV1, /// Extensible marker layout with one PDA per mint. @@ -489,7 +532,7 @@ pub enum EditionMarkerAccountKind { /// Canonical bounded projection of one Edition Marker account. #[derive(Clone, Debug, PartialEq)] -pub struct EditionMarkerAccountSnapshot { +pub struct DcMetadataMtmEditionMarkerAccountSnapshot { /// Canonical account address. pub account: String, /// Canonical PDA bump. @@ -497,7 +540,7 @@ pub struct EditionMarkerAccountSnapshot { /// Mint used to derive the marker PDA. pub mint: String, /// Decoded marker layout. - pub kind: EditionMarkerAccountKind, + pub kind: DcMetadataMtmEditionMarkerAccountKind, /// V1 group number (`edition / 248`), absent for V2. pub marker_group: std::option::Option, /// Requested edition used to inspect the bitmap. @@ -515,23 +558,28 @@ pub struct EditionMarkerAccountSnapshot { } /// Decodes EditionMarker or EditionMarkerV2 with exact owner, bounds, bitmap and PDA validation. -pub fn decode_edition_marker_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_edition_marker_account( account: &str, owner: &str, mint: &str, edition: u64, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmEditionMarkerAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let account_key = match ::from_str(account) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let owner_key = match ::from_str(owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; let program_key = match ::from_str( @@ -539,24 +587,30 @@ pub fn decode_edition_marker_account( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; if owner_key != program_key { - return std::result::Result::Err(MetadataAccountDecodeError::ForeignOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::ForeignOwner); } let mint_key = match ::from_str(mint) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; if data.is_empty() { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } if data[0] == mpl_token_metadata::types::Key::EditionMarker as u8 { if data.len() != mpl_token_metadata::accounts::EditionMarker::LEN { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let marker_group = edition / EDITION_MARKER_V1_BITS; let marker_seed = marker_group.to_string(); @@ -571,12 +625,16 @@ pub fn decode_edition_marker_account( &program_key, ); if account_key != expected_pda { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidEditionMarkerPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidEditionMarkerPda, + ); } let value = match mpl_token_metadata::accounts::EditionMarker::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let offset = (edition % EDITION_MARKER_V1_BITS) as usize; @@ -585,14 +643,16 @@ pub fn decode_edition_marker_account( let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(EditionMarkerAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmEditionMarkerAccountSnapshot { account: account_key.to_string(), bump, mint: mint_key.to_string(), - kind: EditionMarkerAccountKind::EditionMarkerV1, + kind: DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV1, marker_group: std::option::Option::Some(marker_group), edition, byte_index, @@ -604,35 +664,43 @@ pub fn decode_edition_marker_account( } if data[0] == mpl_token_metadata::types::Key::EditionMarkerV2 as u8 { if data.len() < 5 || data.len() > MAX_EDITION_MARKER_V2_LEDGER_BYTES + 5 { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let (expected_pda, bump) = solana_pubkey::Pubkey::find_program_address( &[b"metadata", program_key.as_ref(), mint_key.as_ref(), b"edition", b"marker"], &program_key, ); if account_key != expected_pda { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidEditionMarkerPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidEditionMarkerPda, + ); } let value = match mpl_token_metadata::accounts::EditionMarkerV2::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if value.ledger.len() > MAX_EDITION_MARKER_V2_LEDGER_BYTES { return std::result::Result::Err( - MetadataAccountDecodeError::EditionMarkerBoundsExceeded, + DcMetadataMtmMetadataAccountDecodeError::EditionMarkerBoundsExceeded, ); } if data.len() != value.ledger.len() + 5 { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let byte_index_u64 = edition / 8; let byte_index = match usize::try_from(byte_index_u64) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { return std::result::Result::Err( - MetadataAccountDecodeError::EditionMarkerBoundsExceeded, + DcMetadataMtmMetadataAccountDecodeError::EditionMarkerBoundsExceeded, ); }, }; @@ -642,14 +710,16 @@ pub fn decode_edition_marker_account( let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(EditionMarkerAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmEditionMarkerAccountSnapshot { account: account_key.to_string(), bump, mint: mint_key.to_string(), - kind: EditionMarkerAccountKind::EditionMarkerV2, + kind: DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV2, marker_group: std::option::Option::None, edition, byte_index, @@ -659,12 +729,12 @@ pub fn decode_edition_marker_account( payload_json, }); } - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataKey); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataKey); } /// Canonical bounded projection of one programmable Token Record account. #[derive(Clone, Debug, PartialEq)] -pub struct TokenRecordAccountSnapshot { +pub struct DcMetadataMtmTokenRecordAccountSnapshot { /// Canonical Token Record account address. pub account: String, /// Canonical Token Record PDA bump computed from mint and token account. @@ -692,23 +762,28 @@ pub struct TokenRecordAccountSnapshot { } /// Decodes one Token Record account after exact owner, length, discriminant and PDA validation. -pub fn decode_token_record_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_token_record_account( account: &str, owner: &str, mint: &str, token: &str, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmTokenRecordAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let account_key = match ::from_str(account) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let owner_key = match ::from_str(owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; let expected_owner = match ::from_str( @@ -716,25 +791,31 @@ pub fn decode_token_record_account( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; if owner_key != expected_owner { - return std::result::Result::Err(MetadataAccountDecodeError::ForeignOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::ForeignOwner); } if data.len() != mpl_token_metadata::accounts::TokenRecord::LEN { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let mint_key = match ::from_str(mint) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let token_key = match ::from_str(token) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let (expected_pda, bump) = solana_pubkey::Pubkey::find_program_address( @@ -748,30 +829,40 @@ pub fn decode_token_record_account( &expected_owner, ); if account_key != expected_pda { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidTokenRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidTokenRecordPda, + ); } let value = match mpl_token_metadata::accounts::TokenRecord::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if value.key != mpl_token_metadata::types::Key::TokenRecord { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidTokenRecordKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidTokenRecordKey, + ); } if value.bump != bump { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidTokenRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidTokenRecordPda, + ); } let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; let state = format!("{:?}", value.state); let delegate_role = value.delegate_role.as_ref().map(|role| return format!("{role:?}")); let locked = value.state == mpl_token_metadata::types::TokenState::Locked; - return std::result::Result::Ok(TokenRecordAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmTokenRecordAccountSnapshot { account: account_key.to_string(), bump, mint: mint_key.to_string(), @@ -791,7 +882,7 @@ pub fn decode_token_record_account( /// Canonical projection shared by Metadata and Holder delegate records. #[derive(Clone, Debug, PartialEq)] -pub struct DelegateRecordAccountSnapshot { +pub struct DcMetadataMtmDelegateRecordAccountSnapshot { /// Canonical delegate-record account address. pub account: String, /// Canonical PDA bump. @@ -817,18 +908,22 @@ pub struct DelegateRecordAccountSnapshot { fn parse_record_boundary( account: &str, owner: &str, -) -> std::result::Result<(solana_pubkey::Pubkey, solana_pubkey::Pubkey), MetadataAccountDecodeError> -{ +) -> std::result::Result< + (solana_pubkey::Pubkey, solana_pubkey::Pubkey), + DcMetadataMtmMetadataAccountDecodeError, +> { let account_key = match ::from_str(account) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let owner_key = match ::from_str(owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; let expected_owner = match ::from_str( @@ -836,44 +931,55 @@ fn parse_record_boundary( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; if owner_key != expected_owner { - return std::result::Result::Err(MetadataAccountDecodeError::ForeignOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::ForeignOwner); } return std::result::Result::Ok((account_key, expected_owner)); } /// Decodes a Metadata Delegate Record with exact role, authority, delegate and bump validation. -pub fn decode_metadata_delegate_record_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_metadata_delegate_record_account( account: &str, owner: &str, role: mpl_token_metadata::types::MetadataDelegateRole, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmDelegateRecordAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let (account_key, program) = match parse_record_boundary(account, owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if data.len() != mpl_token_metadata::accounts::MetadataDelegateRecord::LEN { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let value = match mpl_token_metadata::accounts::MetadataDelegateRecord::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if value.key != mpl_token_metadata::types::Key::MetadataDelegate { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordKey, + ); } let role_seed = role.to_string(); let mint = match ::from_str(&value.mint.to_string()) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let authority = match ::from_str( @@ -881,14 +987,18 @@ pub fn decode_metadata_delegate_record_account( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let delegate = match ::from_str(&value.delegate.to_string()) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let (expected_pda, bump) = solana_pubkey::Pubkey::find_program_address( @@ -903,15 +1013,19 @@ pub fn decode_metadata_delegate_record_account( &program, ); if account_key != expected_pda || value.bump != bump { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordPda, + ); } let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(DelegateRecordAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmDelegateRecordAccountSnapshot { account: account_key.to_string(), bump, kind: "MetadataDelegateRecord".to_string(), @@ -926,33 +1040,44 @@ pub fn decode_metadata_delegate_record_account( } /// Decodes a Holder Delegate Record with exact role, holder, delegate and bump validation. -pub fn decode_holder_delegate_record_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_holder_delegate_record_account( account: &str, owner: &str, holder: &str, role: mpl_token_metadata::types::HolderDelegateRole, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmDelegateRecordAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let (account_key, program) = match parse_record_boundary(account, owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if data.len() != mpl_token_metadata::accounts::HolderDelegateRecord::LEN { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let value = match mpl_token_metadata::accounts::HolderDelegateRecord::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if value.key != mpl_token_metadata::types::Key::HolderDelegate { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordKey, + ); } let holder_key = match ::from_str(holder) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let role_seed = role.to_string(); @@ -960,14 +1085,18 @@ pub fn decode_holder_delegate_record_account( { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let delegate = match ::from_str(&value.delegate.to_string()) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let (expected_pda, bump) = solana_pubkey::Pubkey::find_program_address( @@ -982,15 +1111,19 @@ pub fn decode_holder_delegate_record_account( &program, ); if account_key != expected_pda || value.bump != bump { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordPda, + ); } let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(DelegateRecordAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmDelegateRecordAccountSnapshot { account: account_key.to_string(), bump, kind: "HolderDelegateRecord".to_string(), @@ -1006,7 +1139,7 @@ pub fn decode_holder_delegate_record_account( /// Canonical projection of Collection Authority and Use Authority records. #[derive(Clone, Debug, PartialEq)] -pub struct AuthorityRecordAccountSnapshot { +pub struct DcMetadataMtmAuthorityRecordAccountSnapshot { /// Canonical record account address. pub account: String, /// Canonical PDA bump. @@ -1028,30 +1161,39 @@ pub struct AuthorityRecordAccountSnapshot { } /// Decodes a Collection Authority Record with exact PDA and bump validation. -pub fn decode_collection_authority_record_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_collection_authority_record_account( account: &str, owner: &str, mint: &str, authority: &str, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmAuthorityRecordAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let (account_key, program) = match parse_record_boundary(account, owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if data.len() != 3 && data.len() != 35 { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let mint_key = match ::from_str(mint) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let authority_key = match ::from_str(authority) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let (expected_pda, bump) = solana_pubkey::Pubkey::find_program_address( @@ -1065,27 +1207,37 @@ pub fn decode_collection_authority_record_account( &program, ); if account_key != expected_pda { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordPda, + ); } let value = match mpl_token_metadata::accounts::CollectionAuthorityRecord::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if value.key != mpl_token_metadata::types::Key::CollectionAuthorityRecord { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordKey, + ); } if value.bump != bump { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordPda, + ); } let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(AuthorityRecordAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmAuthorityRecordAccountSnapshot { account: account_key.to_string(), bump, kind: "CollectionAuthorityRecord".to_string(), @@ -1099,30 +1251,39 @@ pub fn decode_collection_authority_record_account( } /// Decodes a Use Authority Record with exact length, PDA and bump validation. -pub fn decode_use_authority_record_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account( account: &str, owner: &str, mint: &str, authority: &str, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmAuthorityRecordAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let (account_key, program) = match parse_record_boundary(account, owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if data.len() != mpl_token_metadata::accounts::UseAuthorityRecord::LEN { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let mint_key = match ::from_str(mint) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let authority_key = match ::from_str(authority) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let (expected_pda, bump) = solana_pubkey::Pubkey::find_program_address( @@ -1136,27 +1297,37 @@ pub fn decode_use_authority_record_account( &program, ); if account_key != expected_pda { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordPda, + ); } let value = match mpl_token_metadata::accounts::UseAuthorityRecord::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if value.key != mpl_token_metadata::types::Key::UseAuthorityRecord { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordKey, + ); } if value.bump != bump { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAuthorityRecordPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordPda, + ); } let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(AuthorityRecordAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmAuthorityRecordAccountSnapshot { account: account_key.to_string(), bump, kind: "UseAuthorityRecord".to_string(), @@ -1171,7 +1342,7 @@ pub fn decode_use_authority_record_account( /// Authority form used by one Token Owned Escrow account. #[derive(Clone, Debug, Eq, PartialEq)] -pub enum TokenOwnedEscrowAuthorityKind { +pub enum DcMetadataMtmTokenOwnedEscrowAuthorityKind { /// Escrow controlled by the owner of the base token. TokenOwner, /// Escrow controlled by an explicit creator key. @@ -1180,7 +1351,7 @@ pub enum TokenOwnedEscrowAuthorityKind { /// Canonical bounded projection of one Token Owned Escrow account. #[derive(Clone, Debug, PartialEq)] -pub struct TokenOwnedEscrowAccountSnapshot { +pub struct DcMetadataMtmTokenOwnedEscrowAccountSnapshot { /// Canonical escrow account address. pub account: String, /// Canonical PDA bump. @@ -1188,7 +1359,7 @@ pub struct TokenOwnedEscrowAccountSnapshot { /// Base token mint stored by the account. pub base_token: String, /// Authority form encoded by the account. - pub authority_kind: TokenOwnedEscrowAuthorityKind, + pub authority_kind: DcMetadataMtmTokenOwnedEscrowAuthorityKind, /// Optional creator authority. pub creator: std::option::Option, /// Bump stored by the account. @@ -1198,33 +1369,44 @@ pub struct TokenOwnedEscrowAccountSnapshot { } /// Decodes one Token Owned Escrow account with exact owner, layout, authority seeds and bump validation. -pub fn decode_token_owned_escrow_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account( account: &str, owner: &str, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmTokenOwnedEscrowAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { let (account_key, program) = match parse_record_boundary(account, owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if data.len() != 35 && data.len() != 67 { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); } let value = match mpl_token_metadata::accounts::TokenOwnedEscrow::from_bytes(data) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; if value.key != mpl_token_metadata::types::Key::TokenOwnedEscrow { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidTokenOwnedEscrowKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidTokenOwnedEscrowKey, + ); } let base_token = match ::from_str(&value.base_token.to_string()) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let (authority_kind, creator, expected_pda, bump) = match &value.authority { @@ -1234,7 +1416,7 @@ pub fn decode_token_owned_escrow_account( &program, ); ( - TokenOwnedEscrowAuthorityKind::TokenOwner, + DcMetadataMtmTokenOwnedEscrowAuthorityKind::TokenOwner, std::option::Option::None, expected_pda, bump, @@ -1247,7 +1429,7 @@ pub fn decode_token_owned_escrow_account( std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { return std::result::Result::Err( - MetadataAccountDecodeError::InvalidAccountKey, + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, ); }, }; @@ -1263,7 +1445,7 @@ pub fn decode_token_owned_escrow_account( &program, ); ( - TokenOwnedEscrowAuthorityKind::Creator, + DcMetadataMtmTokenOwnedEscrowAuthorityKind::Creator, std::option::Option::Some(creator_text), expected_pda, bump, @@ -1271,15 +1453,19 @@ pub fn decode_token_owned_escrow_account( }, }; if account_key != expected_pda || value.bump != bump { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidTokenOwnedEscrowPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidTokenOwnedEscrowPda, + ); } let payload_json = match serde_json::to_value(&value) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::ProjectionFailed); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ProjectionFailed, + ); }, }; - return std::result::Result::Ok(TokenOwnedEscrowAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmTokenOwnedEscrowAccountSnapshot { account: account_key.to_string(), bump, base_token: value.base_token.to_string(), @@ -1292,7 +1478,7 @@ pub fn decode_token_owned_escrow_account( /// Historical Reservation List account generation. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum ReservationListAccountKind { +pub enum DcMetadataMtmReservationListAccountKind { /// Legacy layout with `u8` spot counters. V1, /// Later historical layout with `u64` spot counters and cached totals. @@ -1301,7 +1487,7 @@ pub enum ReservationListAccountKind { /// One bounded historical reservation entry. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct ReservationEntrySnapshot { +pub struct DcMetadataMtmReservationEntrySnapshot { /// Reserved address. pub address: String, /// Spots still available for the address. @@ -1312,13 +1498,13 @@ pub struct ReservationEntrySnapshot { /// Canonical decode-only projection of a historical Reservation List account. #[derive(Clone, Debug, PartialEq)] -pub struct ReservationListAccountSnapshot { +pub struct DcMetadataMtmReservationListAccountSnapshot { /// Canonical account address. pub account: String, /// Canonical Reservation List PDA bump. pub bump: u8, /// Historical account generation. - pub kind: ReservationListAccountKind, + pub kind: DcMetadataMtmReservationListAccountKind, /// Master Edition stored by the account. pub master_edition: String, /// Resource key used by the PDA derivation. @@ -1326,7 +1512,7 @@ pub struct ReservationListAccountSnapshot { /// Master Edition supply captured when reservations were created. pub supply_snapshot: std::option::Option, /// Bounded reservation entries. - pub reservations: std::vec::Vec, + pub reservations: std::vec::Vec, /// Total reservation spots. V1 derives this value from entries. pub total_reservation_spots: u64, /// Current reservation spots. V1 derives this value from entries. @@ -1373,31 +1559,38 @@ fn read_reservation_pubkey( } /// Decodes a historical Reservation List V1 or V2 account as decode-only state. -pub fn decode_reservation_list_account( +pub fn decoder_metadata_metaplex_token_metadata_decode_reservation_list_account( account: &str, owner: &str, resource: &str, data: &[u8], -) -> std::result::Result { +) -> std::result::Result< + DcMetadataMtmReservationListAccountSnapshot, + DcMetadataMtmMetadataAccountDecodeError, +> { const MAX_RESERVATIONS: usize = 200; const MAX_V1_BYTES: usize = 6_949; const MAX_V2_BYTES: usize = 9_749; let account_key = match ::from_str(account) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let owner_key = match ::from_str(owner) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; let resource_key = match ::from_str(resource) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidAccountKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidAccountKey, + ); }, }; let program_key = match ::from_str( @@ -1405,39 +1598,49 @@ pub fn decode_reservation_list_account( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::InvalidOwner); }, }; if owner_key != program_key { - return std::result::Result::Err(MetadataAccountDecodeError::ForeignOwner); + return std::result::Result::Err(DcMetadataMtmMetadataAccountDecodeError::ForeignOwner); } let key = match data.first() { std::option::Option::Some(value) => *value, std::option::Option::None => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidDataLength); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength, + ); }, }; let (kind, maximum, entry_bytes) = match key { - 3 => (ReservationListAccountKind::V1, MAX_V1_BYTES, 34usize), - 5 => (ReservationListAccountKind::V2, MAX_V2_BYTES, 48usize), + 3 => (DcMetadataMtmReservationListAccountKind::V1, MAX_V1_BYTES, 34usize), + 5 => (DcMetadataMtmReservationListAccountKind::V2, MAX_V2_BYTES, 48usize), _ => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidReservationListKey); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidReservationListKey, + ); }, }; if data.len() > maximum { - return std::result::Result::Err(MetadataAccountDecodeError::ReservationListBoundsExceeded); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ReservationListBoundsExceeded, + ); } let mut offset = 1usize; let master_edition = match read_reservation_pubkey(data, &mut offset) { std::option::Option::Some(value) => value, std::option::Option::None => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let option_tag = match data.get(offset) { std::option::Option::Some(value) => *value, std::option::Option::None => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; offset += 1; @@ -1446,60 +1649,78 @@ pub fn decode_reservation_list_account( 1 => match read_reservation_u64(data, &mut offset) { std::option::Option::Some(value) => std::option::Option::Some(value), std::option::Option::None => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }, - _ => return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout), + _ => { + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); + }, }; let count_end = match offset.checked_add(4) { std::option::Option::Some(value) => value, std::option::Option::None => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let count_bytes = match data.get(offset..count_end) { std::option::Option::Some(value) => value, std::option::Option::None => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let count_array = match <[u8; 4]>::try_from(count_bytes) { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let count = u32::from_le_bytes(count_array) as usize; offset = count_end; if count > MAX_RESERVATIONS { - return std::result::Result::Err(MetadataAccountDecodeError::ReservationListBoundsExceeded); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::ReservationListBoundsExceeded, + ); } let required_entries = match count.checked_mul(entry_bytes) { std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err( - MetadataAccountDecodeError::ReservationListBoundsExceeded, + DcMetadataMtmMetadataAccountDecodeError::ReservationListBoundsExceeded, ); }, }; if data.len().saturating_sub(offset) < required_entries { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); } let mut reservations = std::vec::Vec::with_capacity(count); for _ in 0..count { let address = match read_reservation_pubkey(data, &mut offset) { std::option::Option::Some(value) => value, std::option::Option::None => { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); }, }; let (spots_remaining, total_spots) = match kind { - ReservationListAccountKind::V1 => { + DcMetadataMtmReservationListAccountKind::V1 => { let remaining = match data.get(offset) { std::option::Option::Some(value) => *value as u64, std::option::Option::None => { return std::result::Result::Err( - MetadataAccountDecodeError::InvalidMetadataLayout, + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, ); }, }; @@ -1507,19 +1728,19 @@ pub fn decode_reservation_list_account( std::option::Option::Some(value) => *value as u64, std::option::Option::None => { return std::result::Result::Err( - MetadataAccountDecodeError::InvalidMetadataLayout, + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, ); }, }; offset += 2; (remaining, total) }, - ReservationListAccountKind::V2 => { + DcMetadataMtmReservationListAccountKind::V2 => { let remaining = match read_reservation_u64(data, &mut offset) { std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err( - MetadataAccountDecodeError::InvalidMetadataLayout, + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, ); }, }; @@ -1527,14 +1748,14 @@ pub fn decode_reservation_list_account( std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err( - MetadataAccountDecodeError::InvalidMetadataLayout, + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, ); }, }; (remaining, total) }, }; - reservations.push(ReservationEntrySnapshot { + reservations.push(DcMetadataMtmReservationEntrySnapshot { address: address.to_string(), spots_remaining, total_spots, @@ -1544,13 +1765,13 @@ pub fn decode_reservation_list_account( .iter() .fold(0u64, |sum, entry| return sum.saturating_add(entry.total_spots)); let (total_reservation_spots, current_reservation_spots) = match kind { - ReservationListAccountKind::V1 => (derived_total, derived_total), - ReservationListAccountKind::V2 => { + DcMetadataMtmReservationListAccountKind::V1 => (derived_total, derived_total), + DcMetadataMtmReservationListAccountKind::V2 => { let total = match read_reservation_u64(data, &mut offset) { std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err( - MetadataAccountDecodeError::InvalidMetadataLayout, + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, ); }, }; @@ -1558,7 +1779,7 @@ pub fn decode_reservation_list_account( std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err( - MetadataAccountDecodeError::InvalidMetadataLayout, + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, ); }, }; @@ -1569,7 +1790,9 @@ pub fn decode_reservation_list_account( .get(offset..) .is_some_and(|suffix| return suffix.iter().any(|byte| return *byte != 0)) { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidMetadataLayout); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout, + ); } let (expected_pda, bump) = solana_pubkey::Pubkey::find_program_address( &[ @@ -1582,10 +1805,12 @@ pub fn decode_reservation_list_account( &program_key, ); if account_key != expected_pda { - return std::result::Result::Err(MetadataAccountDecodeError::InvalidReservationListPda); + return std::result::Result::Err( + DcMetadataMtmMetadataAccountDecodeError::InvalidReservationListPda, + ); } let payload_json = serde_json::json!({ - "kind": match kind { ReservationListAccountKind::V1 => "reservation_list_v1", ReservationListAccountKind::V2 => "reservation_list_v2" }, + "kind": match kind { DcMetadataMtmReservationListAccountKind::V1 => "reservation_list_v1", DcMetadataMtmReservationListAccountKind::V2 => "reservation_list_v2" }, "master_edition": master_edition.to_string(), "resource": resource_key.to_string(), "supply_snapshot": supply_snapshot, @@ -1593,7 +1818,7 @@ pub fn decode_reservation_list_account( "total_reservation_spots": total_reservation_spots, "current_reservation_spots": current_reservation_spots, }); - return std::result::Result::Ok(ReservationListAccountSnapshot { + return std::result::Result::Ok(DcMetadataMtmReservationListAccountSnapshot { account: account_key.to_string(), bump, kind, @@ -1639,15 +1864,14 @@ mod tests { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("metadata serialization failed: {error}"), }; - let snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_metadata_account( - &account.to_string(), - kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, - &data, - ) { - std::result::Result::Ok(value) => value, - std::result::Result::Err(error) => panic!("metadata decode failed: {error}"), - }; + let snapshot = match crate::decoder_metadata_metaplex_token_metadata_decode_metadata_account( + &account.to_string(), + kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, + &data, + ) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("metadata decode failed: {error}"), + }; assert_eq!(snapshot.bump, expected_bump); assert_eq!(snapshot.mint, metadata.mint.to_string()); assert_eq!(snapshot.name, "Khadhroony"); @@ -1666,28 +1890,32 @@ mod tests { std::result::Result::Err(error) => panic!("metadata serialization failed: {error}"), }; assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_metadata_account( + crate::decoder_metadata_metaplex_token_metadata_decode_metadata_account( &account.to_string(), &solana_pubkey::Pubkey::new_unique().to_string(), &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::ForeignOwner), + std::result::Result::Err(crate::DcMetadataMtmMetadataAccountDecodeError::ForeignOwner), ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_metadata_account( + crate::decoder_metadata_metaplex_token_metadata_decode_metadata_account( &solana_pubkey::Pubkey::new_unique().to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidMetadataPda), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataPda + ), ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_metadata_account( + crate::decoder_metadata_metaplex_token_metadata_decode_metadata_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &[] ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidDataLength), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength + ), ); } @@ -1707,7 +1935,7 @@ mod tests { }, }; let master_v2_snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_edition_account( + match crate::decoder_metadata_metaplex_token_metadata_decode_edition_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), @@ -1719,7 +1947,7 @@ mod tests { assert_eq!(master_v2_snapshot.bump, expected_bump); assert_eq!( master_v2_snapshot.kind, - crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::MasterEditionV2 + crate::DcMetadataMtmEditionAccountKind::MasterEditionV2 ); assert_eq!(master_v2_snapshot.supply, std::option::Option::Some(7)); assert_eq!(master_v2_snapshot.max_supply, std::option::Option::Some(100)); @@ -1733,7 +1961,7 @@ mod tests { std::result::Result::Err(error) => panic!("edition serialization failed: {error}"), }; let edition_snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_edition_account( + match crate::decoder_metadata_metaplex_token_metadata_decode_edition_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), @@ -1742,10 +1970,7 @@ mod tests { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("edition decode failed: {error}"), }; - assert_eq!( - edition_snapshot.kind, - crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::EditionV1 - ); + assert_eq!(edition_snapshot.kind, crate::DcMetadataMtmEditionAccountKind::EditionV1); assert_eq!(edition_snapshot.parent, std::option::Option::Some(account.to_string())); assert_eq!(edition_snapshot.edition, std::option::Option::Some(u64::MAX)); } @@ -1767,43 +1992,43 @@ mod tests { panic!("historical master edition serialization failed: {error}") }, }; - let snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_edition_account( - &account.to_string(), - kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, - &mint.to_string(), - &data, - ) { - std::result::Result::Ok(value) => value, - std::result::Result::Err(error) => { - panic!("historical master edition decode failed: {error}") - }, - }; - assert_eq!( - snapshot.kind, - crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::MasterEditionV1 - ); + let snapshot = match crate::decoder_metadata_metaplex_token_metadata_decode_edition_account( + &account.to_string(), + kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, + &mint.to_string(), + &data, + ) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => { + panic!("historical master edition decode failed: {error}") + }, + }; + assert_eq!(snapshot.kind, crate::DcMetadataMtmEditionAccountKind::MasterEditionV1); assert_eq!( snapshot.printing_mint, std::option::Option::Some(mpl_token_metadata::ID.to_string()) ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_edition_account( + crate::decoder_metadata_metaplex_token_metadata_decode_edition_account( &solana_pubkey::Pubkey::new_unique().to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidMetadataPda), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataPda + ), ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_edition_account( + crate::decoder_metadata_metaplex_token_metadata_decode_edition_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &[255] ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidMetadataKey), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataKey + ), ); } @@ -1846,7 +2071,7 @@ mod tests { }, }; let snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_edition_marker_account( + match crate::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint, @@ -1856,7 +2081,7 @@ mod tests { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("edition marker decode failed: {error}"), }; - assert_eq!(snapshot.kind, crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountKind::EditionMarkerV1); + assert_eq!(snapshot.kind, crate::DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV1); assert_eq!(snapshot.bump, expected_bump); assert_eq!(snapshot.marker_group, std::option::Option::Some(1)); assert_eq!(snapshot.byte_index, 0); @@ -1892,7 +2117,7 @@ mod tests { }, }; let snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_edition_marker_account( + match crate::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint, @@ -1904,7 +2129,7 @@ mod tests { panic!("edition marker v2 decode failed: {error}") }, }; - assert_eq!(snapshot.kind, crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountKind::EditionMarkerV2); + assert_eq!(snapshot.kind, crate::DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV2); assert_eq!(snapshot.bump, expected_bump); assert_eq!(snapshot.marker_group, std::option::Option::None); assert_eq!(snapshot.byte_index, 1); @@ -1913,24 +2138,28 @@ mod tests { let mut suffixed = data.clone(); suffixed.push(0); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_edition_marker_account( + crate::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint, 9, &suffixed ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidDataLength), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength + ), ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_edition_marker_account( + crate::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account( &solana_pubkey::Pubkey::new_unique().to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint, 9, &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidEditionMarkerPda), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidEditionMarkerPda + ), ); } @@ -1965,7 +2194,7 @@ mod tests { }; data.resize(mpl_token_metadata::accounts::TokenRecord::LEN, 0); let snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_token_record_account( + match crate::decoder_metadata_metaplex_token_metadata_decode_token_record_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), @@ -2026,57 +2255,65 @@ mod tests { }; let data = make_data(mpl_token_metadata::types::Key::TokenRecord, bump); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_record_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_record_account( &account.to_string(), &solana_pubkey::Pubkey::new_unique().to_string(), &mint.to_string(), &token.to_string(), &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::ForeignOwner), + std::result::Result::Err(crate::DcMetadataMtmMetadataAccountDecodeError::ForeignOwner), ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_record_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_record_account( &solana_pubkey::Pubkey::new_unique().to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &token.to_string(), &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidTokenRecordPda), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidTokenRecordPda + ), ); let wrong_bump = make_data(mpl_token_metadata::types::Key::TokenRecord, bump.wrapping_add(1)); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_record_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_record_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &token.to_string(), &wrong_bump ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidTokenRecordPda), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidTokenRecordPda + ), ); let wrong_key = make_data(mpl_token_metadata::types::Key::MetadataV1, bump); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_record_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_record_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &token.to_string(), &wrong_key ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidTokenRecordKey), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidTokenRecordKey + ), ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_record_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_record_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &token.to_string(), &data[..data.len() - 1] ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidDataLength), + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength + ), ); } @@ -2118,7 +2355,7 @@ mod tests { }, }; assert_eq!(data.len(), mpl_token_metadata::accounts::MetadataDelegateRecord::LEN); - let snapshot = match crate::decoder::metadata::metaplex_token_metadata::decode_metadata_delegate_record_account( + let snapshot = match crate::decoder_metadata_metaplex_token_metadata_decode_metadata_delegate_record_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, role, @@ -2155,7 +2392,7 @@ mod tests { panic!("holder delegate serialization failed: {error}") }, }; - let holder_snapshot = match crate::decoder::metadata::metaplex_token_metadata::decode_holder_delegate_record_account( + let holder_snapshot = match crate::decoder_metadata_metaplex_token_metadata_decode_holder_delegate_record_account( &holder_account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &authority.to_string(), @@ -2200,7 +2437,7 @@ mod tests { panic!("collection authority serialization failed: {error}") }, }; - let collection_snapshot = match crate::decoder::metadata::metaplex_token_metadata::decode_collection_authority_record_account( + let collection_snapshot = match crate::decoder_metadata_metaplex_token_metadata_decode_collection_authority_record_account( &collection_account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), @@ -2231,7 +2468,7 @@ mod tests { panic!("use authority serialization failed: {error}") }, }; - let use_snapshot = match crate::decoder::metadata::metaplex_token_metadata::decode_use_authority_record_account( + let use_snapshot = match crate::decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account( &use_account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), @@ -2243,24 +2480,28 @@ mod tests { }; assert_eq!(use_snapshot.allowed_uses, std::option::Option::Some(u64::MAX)); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_use_authority_record_account( + crate::decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account( &solana_pubkey::Pubkey::new_unique().to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &authority.to_string(), &use_data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidAuthorityRecordPda) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidAuthorityRecordPda + ) ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_use_authority_record_account( + crate::decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account( &use_account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &mint.to_string(), &authority.to_string(), &use_data[..9] ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidDataLength) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength + ) ); } @@ -2289,15 +2530,19 @@ mod tests { std::result::Result::Err(error) => panic!("escrow serialization failed: {error}"), }; assert_eq!(owner_data.len(), 35); - let owner_snapshot = match crate::decoder::metadata::metaplex_token_metadata::decode_token_owned_escrow_account( - &owner_account.to_string(), - kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, - &owner_data, - ) { - std::result::Result::Ok(value) => value, - std::result::Result::Err(error) => panic!("escrow decode failed: {error}"), - }; - assert_eq!(owner_snapshot.authority_kind, crate::decoder::metadata::metaplex_token_metadata::TokenOwnedEscrowAuthorityKind::TokenOwner); + let owner_snapshot = + match crate::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account( + &owner_account.to_string(), + kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, + &owner_data, + ) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("escrow decode failed: {error}"), + }; + assert_eq!( + owner_snapshot.authority_kind, + crate::DcMetadataMtmTokenOwnedEscrowAuthorityKind::TokenOwner + ); assert_eq!(owner_snapshot.creator, std::option::Option::None); let creator = mpl_token_metadata::ID; let (creator_account, creator_bump) = solana_pubkey::Pubkey::find_program_address( @@ -2324,15 +2569,19 @@ mod tests { }, }; assert_eq!(creator_data.len(), 67); - let creator_snapshot = match crate::decoder::metadata::metaplex_token_metadata::decode_token_owned_escrow_account( - &creator_account.to_string(), - kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, - &creator_data, - ) { - std::result::Result::Ok(value) => value, - std::result::Result::Err(error) => panic!("creator escrow decode failed: {error}"), - }; - assert_eq!(creator_snapshot.authority_kind, crate::decoder::metadata::metaplex_token_metadata::TokenOwnedEscrowAuthorityKind::Creator); + let creator_snapshot = + match crate::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account( + &creator_account.to_string(), + kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, + &creator_data, + ) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("creator escrow decode failed: {error}"), + }; + assert_eq!( + creator_snapshot.authority_kind, + crate::DcMetadataMtmTokenOwnedEscrowAuthorityKind::Creator + ); assert_eq!( creator_snapshot.creator, std::option::Option::Some(mpl_token_metadata::ID.to_string()) @@ -2365,39 +2614,47 @@ mod tests { }; let data = make(mpl_token_metadata::types::Key::TokenOwnedEscrow, bump); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_owned_escrow_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account( &solana_pubkey::Pubkey::new_unique().to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidTokenOwnedEscrowPda) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidTokenOwnedEscrowPda + ) ); let wrong_bump = make(mpl_token_metadata::types::Key::TokenOwnedEscrow, bump.wrapping_add(1)); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_owned_escrow_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &wrong_bump ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidTokenOwnedEscrowPda) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidTokenOwnedEscrowPda + ) ); let wrong_key = make(mpl_token_metadata::types::Key::MetadataV1, bump); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_owned_escrow_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &wrong_key ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidTokenOwnedEscrowKey) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidTokenOwnedEscrowKey + ) ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_token_owned_escrow_account( + crate::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &data[..34] ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidDataLength) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidDataLength + ) ); } @@ -2431,7 +2688,7 @@ mod tests { v1.push(2); v1.push(3); let snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_reservation_list_account( + match crate::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &resource.to_string(), @@ -2440,10 +2697,7 @@ mod tests { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("reservation v1 decode failed: {error}"), }; - assert_eq!( - snapshot.kind, - crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V1 - ); + assert_eq!(snapshot.kind, crate::DcMetadataMtmReservationListAccountKind::V1); assert_eq!(snapshot.supply_snapshot, std::option::Option::Some(9)); assert_eq!(snapshot.total_reservation_spots, 3); let mut v2 = vec![5u8]; @@ -2456,7 +2710,7 @@ mod tests { v2.extend_from_slice(&11u64.to_le_bytes()); v2.extend_from_slice(&5u64.to_le_bytes()); let snapshot = - match crate::decoder::metadata::metaplex_token_metadata::decode_reservation_list_account( + match crate::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &resource.to_string(), @@ -2465,10 +2719,7 @@ mod tests { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("reservation v2 decode failed: {error}"), }; - assert_eq!( - snapshot.kind, - crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V2 - ); + assert_eq!(snapshot.kind, crate::DcMetadataMtmReservationListAccountKind::V2); assert_eq!(snapshot.reservations[0].spots_remaining, u64::MAX); assert_eq!(snapshot.total_reservation_spots, 11); assert_eq!(snapshot.current_reservation_spots, 5); @@ -2493,19 +2744,14 @@ mod tests { mpl_token_metadata::types::Key::EditionMarkerV2, mpl_token_metadata::types::Key::HolderDelegate, ]; - assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::METADATA_ACCOUNT_LAYOUT_AUDIT.len(), - variants.len() - ); + assert_eq!(crate::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT.len(), variants.len()); for (index, variant) in variants.iter().enumerate() { let bytes = match borsh_0_10::to_vec(variant) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("key serialization failed: {error}"), }; assert_eq!(bytes, vec![index as u8]); - let entry = - crate::decoder::metadata::metaplex_token_metadata::METADATA_ACCOUNT_LAYOUT_AUDIT - [index]; + let entry = crate::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT[index]; assert_eq!(entry.discriminant, index as u8); assert!(!entry.key_name.is_empty()); assert!(!entry.decoder.is_empty()); @@ -2517,9 +2763,7 @@ mod tests { fn account_audit_matrix_covers_every_key_without_duplicate_discriminants() { let mut discriminants = std::collections::BTreeSet::new(); let mut names = std::collections::BTreeSet::new(); - for entry in - crate::decoder::metadata::metaplex_token_metadata::METADATA_ACCOUNT_LAYOUT_AUDIT - { + for entry in crate::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT { assert!(discriminants.insert(entry.discriminant)); assert!(names.insert(entry.key_name)); if entry.discriminant == 0 { @@ -2539,10 +2783,7 @@ mod tests { std::option::Option::Some(value) => value, std::option::Option::None => panic!("account_key_inventory missing"), }; - assert_eq!( - inventory.len(), - crate::decoder::metadata::metaplex_token_metadata::METADATA_ACCOUNT_LAYOUT_AUDIT.len() - ); + assert_eq!(inventory.len(), crate::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT.len()); for (index, item) in inventory.iter().enumerate() { assert_eq!( item.get("discriminant").and_then(serde_json::Value::as_u64), @@ -2550,11 +2791,15 @@ mod tests { ); assert_eq!( item.get("key").and_then(serde_json::Value::as_str), - std::option::Option::Some(crate::decoder::metadata::metaplex_token_metadata::METADATA_ACCOUNT_LAYOUT_AUDIT[index].key_name) + std::option::Option::Some( + crate::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT[index].key_name + ) ); assert_eq!( item.get("decoder").and_then(serde_json::Value::as_str), - std::option::Option::Some(crate::decoder::metadata::metaplex_token_metadata::METADATA_ACCOUNT_LAYOUT_AUDIT[index].decoder) + std::option::Option::Some( + crate::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT[index].decoder + ) ); } } @@ -2584,48 +2829,54 @@ mod tests { data.push(0); data.extend_from_slice(&0u32.to_le_bytes()); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_reservation_list_account( + crate::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account( &solana_pubkey::Pubkey::new_unique().to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &resource.to_string(), &data ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidReservationListPda) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidReservationListPda + ) ); let mut wrong_key = data.clone(); wrong_key[0] = 4; assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_reservation_list_account( + crate::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &resource.to_string(), &wrong_key ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidReservationListKey) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidReservationListKey + ) ); let mut too_many = data.clone(); too_many[34..38].copy_from_slice(&201u32.to_le_bytes()); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_reservation_list_account( + crate::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &resource.to_string(), &too_many ), std::result::Result::Err( - crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::ReservationListBoundsExceeded + crate::DcMetadataMtmMetadataAccountDecodeError::ReservationListBoundsExceeded ) ); let mut suffix = data.clone(); suffix.push(1); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::decode_reservation_list_account( + crate::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account( &account.to_string(), kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, &resource.to_string(), &suffix ), - std::result::Result::Err(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountDecodeError::InvalidMetadataLayout) + std::result::Result::Err( + crate::DcMetadataMtmMetadataAccountDecodeError::InvalidMetadataLayout + ) ); } } diff --git a/kb-lib/src/decoder/metadata/metaplex_token_metadata/canonical.rs b/kb-lib/src/decoder/metadata/metaplex_token_metadata/canonical.rs index 702ec94..bf350e7 100644 --- a/kb-lib/src/decoder/metadata/metaplex_token_metadata/canonical.rs +++ b/kb-lib/src/decoder/metadata/metaplex_token_metadata/canonical.rs @@ -5,7 +5,7 @@ /// Lifecycle class of one decoded Metaplex account layout. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum CanonicalAccountLifecycle { +pub enum DcMetadataMtmCanonicalAccountLifecycle { /// Current account layout used by supported runtime flows. Active, /// Published account layout whose runtime surface is still experimental. @@ -16,7 +16,7 @@ pub enum CanonicalAccountLifecycle { /// Materialization policy attached to one canonical account snapshot. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum CanonicalMaterializationPolicy { +pub enum DcMetadataMtmCanonicalMaterializationPolicy { /// Materialize the latest committed state of an active account. ActiveState, /// Materialize historical state with explicit lifecycle provenance. @@ -25,7 +25,7 @@ pub enum CanonicalMaterializationPolicy { /// Execution policy attached to one canonical account layout. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum CanonicalExecutionPolicy { +pub enum DcMetadataMtmCanonicalExecutionPolicy { /// The layout belongs to current operations that may later be executable. CurrentCandidate, /// The layout belongs to an experimental operation requiring explicit activation. @@ -36,7 +36,7 @@ pub enum CanonicalExecutionPolicy { /// Origin of one canonical account observation. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum CanonicalObservationSource { +pub enum DcMetadataMtmCanonicalObservationSource { /// Account observed from a live subscription or direct live read. Live, /// Account reconstructed while replaying already stored transactions. @@ -51,9 +51,9 @@ pub enum CanonicalObservationSource { /// Provenance retained for one canonical account observation. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct CanonicalAccountProvenance { +pub struct DcMetadataMtmCanonicalAccountProvenance { /// Observation source. - pub source: CanonicalObservationSource, + pub source: DcMetadataMtmCanonicalObservationSource, /// Slot associated with the account state when known. pub slot: std::option::Option, /// Provider write version when available. @@ -70,7 +70,7 @@ pub struct CanonicalAccountProvenance { /// Stable identity and policy of one canonical Metaplex account snapshot. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct CanonicalAccountIdentity { +pub struct DcMetadataMtmCanonicalAccountIdentity { /// Stable identity formed from program id and canonical account address. pub stable_id: String, /// Canonical Metaplex Token Metadata program id. @@ -84,74 +84,73 @@ pub struct CanonicalAccountIdentity { /// Internal canonical-model version. pub canonical_version: u16, /// Published lifecycle class. - pub lifecycle: CanonicalAccountLifecycle, + pub lifecycle: DcMetadataMtmCanonicalAccountLifecycle, /// Materialization policy, including historical backfill state. - pub materialization: CanonicalMaterializationPolicy, + pub materialization: DcMetadataMtmCanonicalMaterializationPolicy, /// Execution policy separated from materialization. - pub execution: CanonicalExecutionPolicy, + pub execution: DcMetadataMtmCanonicalExecutionPolicy, } /// Typed state carried by one canonical Metaplex account snapshot. #[derive(Clone, Debug, PartialEq)] -pub enum CanonicalMetadataAccountState { +pub enum DcMetadataMtmCanonicalMetadataAccountState { /// Metadata account state. - Metadata(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountSnapshot), + Metadata(crate::DcMetadataMtmMetadataAccountSnapshot), /// Master Edition or printed Edition state. - Edition(crate::decoder::metadata::metaplex_token_metadata::EditionAccountSnapshot), + Edition(crate::DcMetadataMtmEditionAccountSnapshot), /// Edition Marker state. - EditionMarker(crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountSnapshot), + EditionMarker(crate::DcMetadataMtmEditionMarkerAccountSnapshot), /// Programmable Token Record state. - TokenRecord(crate::decoder::metadata::metaplex_token_metadata::TokenRecordAccountSnapshot), + TokenRecord(crate::DcMetadataMtmTokenRecordAccountSnapshot), /// Metadata or holder delegate state. - DelegateRecord( - crate::decoder::metadata::metaplex_token_metadata::DelegateRecordAccountSnapshot, - ), + DelegateRecord(crate::DcMetadataMtmDelegateRecordAccountSnapshot), /// Collection or use authority state. - AuthorityRecord( - crate::decoder::metadata::metaplex_token_metadata::AuthorityRecordAccountSnapshot, - ), + AuthorityRecord(crate::DcMetadataMtmAuthorityRecordAccountSnapshot), /// Token-owned escrow state. - TokenOwnedEscrow( - crate::decoder::metadata::metaplex_token_metadata::TokenOwnedEscrowAccountSnapshot, - ), + TokenOwnedEscrow(crate::DcMetadataMtmTokenOwnedEscrowAccountSnapshot), /// Historical Reservation List state. - ReservationList( - crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountSnapshot, - ), + ReservationList(crate::DcMetadataMtmReservationListAccountSnapshot), } /// Canonical envelope used by future materializers and stateful replay. #[derive(Clone, Debug, PartialEq)] -pub struct CanonicalMetadataAccountSnapshot { +pub struct DcMetadataMtmCanonicalMetadataAccountSnapshot { /// Stable identity and lifecycle policy. - pub identity: CanonicalAccountIdentity, + pub identity: DcMetadataMtmCanonicalAccountIdentity, /// Observation provenance. - pub provenance: CanonicalAccountProvenance, + pub provenance: DcMetadataMtmCanonicalAccountProvenance, /// Typed bounded state. - pub state: CanonicalMetadataAccountState, + pub state: DcMetadataMtmCanonicalMetadataAccountState, } fn canonical_identity( account: &str, layout: &str, discriminant: u8, - lifecycle: CanonicalAccountLifecycle, -) -> CanonicalAccountIdentity { + lifecycle: DcMetadataMtmCanonicalAccountLifecycle, +) -> DcMetadataMtmCanonicalAccountIdentity { let program_id = kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID.to_string(); let materialization = match lifecycle { - CanonicalAccountLifecycle::Historical => CanonicalMaterializationPolicy::HistoricalState, - CanonicalAccountLifecycle::Active | CanonicalAccountLifecycle::ActiveExperimental => { - CanonicalMaterializationPolicy::ActiveState + DcMetadataMtmCanonicalAccountLifecycle::Historical => { + DcMetadataMtmCanonicalMaterializationPolicy::HistoricalState + }, + DcMetadataMtmCanonicalAccountLifecycle::Active + | DcMetadataMtmCanonicalAccountLifecycle::ActiveExperimental => { + DcMetadataMtmCanonicalMaterializationPolicy::ActiveState }, }; let execution = match lifecycle { - CanonicalAccountLifecycle::Historical => CanonicalExecutionPolicy::NeverHistorical, - CanonicalAccountLifecycle::Active => CanonicalExecutionPolicy::CurrentCandidate, - CanonicalAccountLifecycle::ActiveExperimental => { - CanonicalExecutionPolicy::ExperimentalCandidate + DcMetadataMtmCanonicalAccountLifecycle::Historical => { + DcMetadataMtmCanonicalExecutionPolicy::NeverHistorical + }, + DcMetadataMtmCanonicalAccountLifecycle::Active => { + DcMetadataMtmCanonicalExecutionPolicy::CurrentCandidate + }, + DcMetadataMtmCanonicalAccountLifecycle::ActiveExperimental => { + DcMetadataMtmCanonicalExecutionPolicy::ExperimentalCandidate }, }; - return CanonicalAccountIdentity { + return DcMetadataMtmCanonicalAccountIdentity { stable_id: format!("{program_id}:{account}"), program_id, account: account.to_string(), @@ -164,102 +163,102 @@ fn canonical_identity( }; } -impl CanonicalMetadataAccountSnapshot { +impl DcMetadataMtmCanonicalMetadataAccountSnapshot { /// Wraps one Metadata account snapshot with stable identity and provenance. pub fn from_metadata( - snapshot: crate::decoder::metadata::metaplex_token_metadata::MetadataAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmMetadataAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let identity = canonical_identity( &snapshot.account, "MetadataV1", mpl_token_metadata::types::Key::MetadataV1 as u8, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ); return Self { identity, provenance, - state: CanonicalMetadataAccountState::Metadata(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::Metadata(snapshot), }; } /// Wraps one Edition or Master Edition snapshot with exact lifecycle policy. pub fn from_edition( - snapshot: crate::decoder::metadata::metaplex_token_metadata::EditionAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmEditionAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let (layout, discriminant, lifecycle) = match snapshot.kind { - crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::MasterEditionV1 => ( + crate::DcMetadataMtmEditionAccountKind::MasterEditionV1 => ( "MasterEditionV1", mpl_token_metadata::types::Key::MasterEditionV1 as u8, - CanonicalAccountLifecycle::Historical, + DcMetadataMtmCanonicalAccountLifecycle::Historical, ), - crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::MasterEditionV2 => ( + crate::DcMetadataMtmEditionAccountKind::MasterEditionV2 => ( "MasterEditionV2", mpl_token_metadata::types::Key::MasterEditionV2 as u8, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ), - crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::EditionV1 => ( + crate::DcMetadataMtmEditionAccountKind::EditionV1 => ( "EditionV1", mpl_token_metadata::types::Key::EditionV1 as u8, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ), }; let identity = canonical_identity(&snapshot.account, layout, discriminant, lifecycle); return Self { identity, provenance, - state: CanonicalMetadataAccountState::Edition(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::Edition(snapshot), }; } /// Wraps one Edition Marker snapshot with exact lifecycle policy. pub fn from_edition_marker( - snapshot: crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmEditionMarkerAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let (layout, discriminant, lifecycle) = match snapshot.kind { - crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountKind::EditionMarkerV1 => ( + crate::DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV1 => ( "EditionMarker", mpl_token_metadata::types::Key::EditionMarker as u8, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ), - crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountKind::EditionMarkerV2 => ( + crate::DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV2 => ( "EditionMarkerV2", mpl_token_metadata::types::Key::EditionMarkerV2 as u8, - CanonicalAccountLifecycle::ActiveExperimental, + DcMetadataMtmCanonicalAccountLifecycle::ActiveExperimental, ), }; let identity = canonical_identity(&snapshot.account, layout, discriminant, lifecycle); return Self { identity, provenance, - state: CanonicalMetadataAccountState::EditionMarker(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::EditionMarker(snapshot), }; } /// Wraps one Token Record snapshot. pub fn from_token_record( - snapshot: crate::decoder::metadata::metaplex_token_metadata::TokenRecordAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmTokenRecordAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let identity = canonical_identity( &snapshot.account, "TokenRecord", mpl_token_metadata::types::Key::TokenRecord as u8, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ); return Self { identity, provenance, - state: CanonicalMetadataAccountState::TokenRecord(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::TokenRecord(snapshot), }; } /// Wraps one Metadata or Holder Delegate snapshot. pub fn from_delegate_record( - snapshot: crate::decoder::metadata::metaplex_token_metadata::DelegateRecordAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmDelegateRecordAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let (layout, discriminant) = if snapshot.kind == "MetadataDelegateRecord" { ("MetadataDelegate", mpl_token_metadata::types::Key::MetadataDelegate as u8) @@ -270,19 +269,19 @@ impl CanonicalMetadataAccountSnapshot { &snapshot.account, layout, discriminant, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ); return Self { identity, provenance, - state: CanonicalMetadataAccountState::DelegateRecord(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::DelegateRecord(snapshot), }; } /// Wraps one Collection or Use Authority snapshot. pub fn from_authority_record( - snapshot: crate::decoder::metadata::metaplex_token_metadata::AuthorityRecordAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmAuthorityRecordAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let (layout, discriminant) = if snapshot.kind == "CollectionAuthorityRecord" { ( @@ -296,43 +295,43 @@ impl CanonicalMetadataAccountSnapshot { &snapshot.account, layout, discriminant, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ); return Self { identity, provenance, - state: CanonicalMetadataAccountState::AuthorityRecord(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::AuthorityRecord(snapshot), }; } /// Wraps one Token Owned Escrow snapshot. pub fn from_token_owned_escrow( - snapshot: crate::decoder::metadata::metaplex_token_metadata::TokenOwnedEscrowAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmTokenOwnedEscrowAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let identity = canonical_identity( &snapshot.account, "TokenOwnedEscrow", mpl_token_metadata::types::Key::TokenOwnedEscrow as u8, - CanonicalAccountLifecycle::Active, + DcMetadataMtmCanonicalAccountLifecycle::Active, ); return Self { identity, provenance, - state: CanonicalMetadataAccountState::TokenOwnedEscrow(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::TokenOwnedEscrow(snapshot), }; } /// Wraps one historical Reservation List snapshot as materializable historical state. pub fn from_reservation_list( - snapshot: crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountSnapshot, - provenance: CanonicalAccountProvenance, + snapshot: crate::DcMetadataMtmReservationListAccountSnapshot, + provenance: DcMetadataMtmCanonicalAccountProvenance, ) -> Self { let (layout, discriminant) = match snapshot.kind { - crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V1 => { + crate::DcMetadataMtmReservationListAccountKind::V1 => { ("ReservationListV1", mpl_token_metadata::types::Key::ReservationListV1 as u8) }, - crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V2 => { + crate::DcMetadataMtmReservationListAccountKind::V2 => { ("ReservationListV2", mpl_token_metadata::types::Key::ReservationListV2 as u8) }, }; @@ -340,12 +339,12 @@ impl CanonicalMetadataAccountSnapshot { &snapshot.account, layout, discriminant, - CanonicalAccountLifecycle::Historical, + DcMetadataMtmCanonicalAccountLifecycle::Historical, ); return Self { identity, provenance, - state: CanonicalMetadataAccountState::ReservationList(snapshot), + state: DcMetadataMtmCanonicalMetadataAccountState::ReservationList(snapshot), }; } } @@ -354,10 +353,10 @@ impl CanonicalMetadataAccountSnapshot { mod tests { #[test] fn historical_state_is_materializable_but_never_executable() { - let snapshot = crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountSnapshot { + let snapshot = crate::DcMetadataMtmReservationListAccountSnapshot { account: "reservation-account".to_string(), bump: 1, - kind: crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V1, + kind: crate::DcMetadataMtmReservationListAccountKind::V1, master_edition: "master-edition".to_string(), resource: "resource".to_string(), supply_snapshot: std::option::Option::Some(7), @@ -366,8 +365,8 @@ mod tests { current_reservation_spots: 0, payload_json: serde_json::json!({}), }; - let provenance = super::CanonicalAccountProvenance { - source: super::CanonicalObservationSource::Backfill, + let provenance = super::DcMetadataMtmCanonicalAccountProvenance { + source: super::DcMetadataMtmCanonicalObservationSource::Backfill, slot: std::option::Option::Some(42), write_version: std::option::Option::None, signature: std::option::Option::Some("historical-signature".to_string()), @@ -375,21 +374,31 @@ mod tests { inner_instruction_index: std::option::Option::None, committed: true, }; - let canonical = - super::CanonicalMetadataAccountSnapshot::from_reservation_list(snapshot, provenance); - assert_eq!(canonical.identity.lifecycle, super::CanonicalAccountLifecycle::Historical); + let canonical = super::DcMetadataMtmCanonicalMetadataAccountSnapshot::from_reservation_list( + snapshot, provenance, + ); + assert_eq!( + canonical.identity.lifecycle, + super::DcMetadataMtmCanonicalAccountLifecycle::Historical + ); assert_eq!( canonical.identity.materialization, - super::CanonicalMaterializationPolicy::HistoricalState + super::DcMetadataMtmCanonicalMaterializationPolicy::HistoricalState + ); + assert_eq!( + canonical.identity.execution, + super::DcMetadataMtmCanonicalExecutionPolicy::NeverHistorical + ); + assert_eq!( + canonical.provenance.source, + super::DcMetadataMtmCanonicalObservationSource::Backfill ); - assert_eq!(canonical.identity.execution, super::CanonicalExecutionPolicy::NeverHistorical); - assert_eq!(canonical.provenance.source, super::CanonicalObservationSource::Backfill); assert!(canonical.identity.stable_id.ends_with(":reservation-account")); } #[test] fn active_and_experimental_layouts_keep_distinct_policies() { - let metadata = crate::decoder::metadata::metaplex_token_metadata::MetadataAccountSnapshot { + let metadata = crate::DcMetadataMtmMetadataAccountSnapshot { account: "metadata-account".to_string(), bump: 1, mint: "mint".to_string(), @@ -402,8 +411,8 @@ mod tests { is_mutable: true, payload_json: serde_json::json!({}), }; - let provenance = super::CanonicalAccountProvenance { - source: super::CanonicalObservationSource::Live, + let provenance = super::DcMetadataMtmCanonicalAccountProvenance { + source: super::DcMetadataMtmCanonicalObservationSource::Live, slot: std::option::Option::Some(1), write_version: std::option::Option::Some(2), signature: std::option::Option::None, @@ -411,14 +420,21 @@ mod tests { inner_instruction_index: std::option::Option::None, committed: true, }; - let canonical = - super::CanonicalMetadataAccountSnapshot::from_metadata(metadata, provenance); - assert_eq!(canonical.identity.lifecycle, super::CanonicalAccountLifecycle::Active); + let canonical = super::DcMetadataMtmCanonicalMetadataAccountSnapshot::from_metadata( + metadata, provenance, + ); + assert_eq!( + canonical.identity.lifecycle, + super::DcMetadataMtmCanonicalAccountLifecycle::Active + ); assert_eq!( canonical.identity.materialization, - super::CanonicalMaterializationPolicy::ActiveState + super::DcMetadataMtmCanonicalMaterializationPolicy::ActiveState + ); + assert_eq!( + canonical.identity.execution, + super::DcMetadataMtmCanonicalExecutionPolicy::CurrentCandidate ); - assert_eq!(canonical.identity.execution, super::CanonicalExecutionPolicy::CurrentCandidate); assert_eq!(canonical.identity.discriminant, 4); assert_eq!(canonical.identity.canonical_version, 1); } diff --git a/kb-lib/src/decoder/metadata/metaplex_token_metadata/constants.rs b/kb-lib/src/decoder/metadata/metaplex_token_metadata/constants.rs index e169601..a8bcb59 100644 --- a/kb-lib/src/decoder/metadata/metaplex_token_metadata/constants.rs +++ b/kb-lib/src/decoder/metadata/metaplex_token_metadata/constants.rs @@ -4,254 +4,325 @@ //! Internal constants for Metaplex Token Metadata decoding. /// Stable decoder surface code. -pub(crate) const SURFACE_CODE: &str = "metadata_metaplex_token_metadata"; +pub(crate) const DC_METADATA_MTM_SURFACE_CODE: &str = "metadata_metaplex_token_metadata"; /// Maximum retained instruction payload size. -pub(crate) const MAX_INSTRUCTION_BYTES: usize = 16_384; +pub(crate) const DC_METADATA_MTM_MAX_INSTRUCTION_BYTES: usize = 16_384; /// Maximum encoded base64 instruction payload size. -pub(crate) const MAX_BASE64_BYTES: usize = 21_852; +pub(crate) const DC_METADATA_MTM_MAX_BASE64_BYTES: usize = 21_852; /// Maximum number of instruction accounts accepted by this decoder. -pub(crate) const MAX_INSTRUCTION_ACCOUNTS: usize = 64; +pub(crate) const DC_METADATA_MTM_MAX_INSTRUCTION_ACCOUNTS: usize = 64; /// Number of bytes retained in malformed-wire diagnostics. -pub(crate) const DIAGNOSTIC_PREFIX_BYTES: usize = 32; +pub(crate) const DC_METADATA_MTM_DIAGNOSTIC_PREFIX_BYTES: usize = 32; /// Stable event payload contract version. -pub(crate) const EVENT_VERSION: u32 = 1; +pub(crate) const DC_METADATA_MTM_EVENT_VERSION: u32 = 1; /// Deprecated Create Master Edition discriminator. -pub(crate) const DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR: u8 = 2; +pub(crate) const DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR: u8 = 2; /// Deprecated Set Reservation List discriminator. -pub(crate) const DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR: u8 = 5; +pub(crate) const DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR: u8 = 5; /// Deprecated Create Reservation List discriminator. -pub(crate) const DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR: u8 = 6; +pub(crate) const DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR: u8 = 6; /// Deprecated Mint Printing Tokens Via Token discriminator. -pub(crate) const DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR: u8 = 8; +pub(crate) const DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR: u8 = 8; /// Deprecated Mint Printing Tokens discriminator. -pub(crate) const DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR: u8 = 9; +pub(crate) const DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR: u8 = 9; /// Historical Create Master Edition discriminator. -pub(crate) const CREATE_MASTER_EDITION_DISCRIMINATOR: u8 = 10; +pub(crate) const DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR: u8 = 10; /// Deprecated printing-token mint-new-edition discriminator. -pub(crate) const DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR: u8 = 3; +pub(crate) const DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR: u8 = + 3; /// Historical Create Metadata Account discriminator. -pub(crate) const CREATE_METADATA_ACCOUNT_DISCRIMINATOR: u8 = 0; +pub(crate) const DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR: u8 = 0; /// Historical Update Metadata Account discriminator. -pub(crate) const UPDATE_METADATA_ACCOUNT_DISCRIMINATOR: u8 = 1; +pub(crate) const DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR: u8 = 1; /// Historical Create Metadata Account V2 discriminator. -pub(crate) const CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR: u8 = 16; +pub(crate) const DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR: u8 = 16; /// Create Metadata Account V3 discriminator. -pub(crate) const CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR: u8 = 33; +pub(crate) const DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR: u8 = 33; /// Update Metadata Account V2 discriminator. -pub(crate) const UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR: u8 = 15; +pub(crate) const DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR: u8 = 15; /// Verify Collection discriminator. -pub(crate) const VERIFY_COLLECTION_DISCRIMINATOR: u8 = 18; +pub(crate) const DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR: u8 = 18; /// Unverify Collection discriminator. -pub(crate) const UNVERIFY_COLLECTION_DISCRIMINATOR: u8 = 22; +pub(crate) const DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR: u8 = 22; /// Set And Verify Collection discriminator. -pub(crate) const SET_AND_VERIFY_COLLECTION_DISCRIMINATOR: u8 = 25; +pub(crate) const DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR: u8 = 25; /// Approve Collection Authority discriminator. -pub(crate) const APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR: u8 = 23; +pub(crate) const DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR: u8 = 23; /// Revoke Collection Authority discriminator. -pub(crate) const REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR: u8 = 24; +pub(crate) const DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR: u8 = 24; /// Verify Sized Collection Item discriminator. -pub(crate) const VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 30; +pub(crate) const DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 30; /// Unverify Sized Collection Item discriminator. -pub(crate) const UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 31; +pub(crate) const DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 31; /// Set And Verify Sized Collection Item discriminator. -pub(crate) const SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 32; +pub(crate) const DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 32; /// Sign Metadata discriminator. -pub(crate) const SIGN_METADATA_DISCRIMINATOR: u8 = 7; +pub(crate) const DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR: u8 = 7; /// Update Primary Sale Happened Via Token discriminator. -pub(crate) const UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR: u8 = 4; +pub(crate) const DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR: u8 = 4; /// Utilize discriminator. -pub(crate) const UTILIZE_DISCRIMINATOR: u8 = 19; +pub(crate) const DC_METADATA_MTM_UTILIZE_DISCRIMINATOR: u8 = 19; /// Approve Use Authority discriminator. -pub(crate) const APPROVE_USE_AUTHORITY_DISCRIMINATOR: u8 = 20; +pub(crate) const DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR: u8 = 20; /// Revoke Use Authority discriminator. -pub(crate) const REVOKE_USE_AUTHORITY_DISCRIMINATOR: u8 = 21; +pub(crate) const DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR: u8 = 21; /// Puff Metadata discriminator. -pub(crate) const PUFF_METADATA_DISCRIMINATOR: u8 = 14; +pub(crate) const DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR: u8 = 14; /// Freeze Delegated Account discriminator. -pub(crate) const FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR: u8 = 26; +pub(crate) const DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR: u8 = 26; /// Thaw Delegated Account discriminator. -pub(crate) const THAW_DELEGATED_ACCOUNT_DISCRIMINATOR: u8 = 27; +pub(crate) const DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR: u8 = 27; /// Remove Creator Verification discriminator. -pub(crate) const REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR: u8 = 28; +pub(crate) const DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR: u8 = 28; /// Set Token Standard discriminator. -pub(crate) const SET_TOKEN_STANDARD_DISCRIMINATOR: u8 = 35; +pub(crate) const DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR: u8 = 35; /// Mint New Edition From Master Edition Via Token discriminator. -pub(crate) const MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR: u8 = 11; +pub(crate) const DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR: u8 = + 11; /// Mint New Edition From Master Edition Via Vault Proxy discriminator. -pub(crate) const MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR: u8 = 13; +pub(crate) const DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR: u8 = 13; /// Convert Master Edition V1 to V2 discriminator. -pub(crate) const CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR: u8 = 12; +pub(crate) const DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR: u8 = 12; /// Create Master Edition V3 discriminator. -pub(crate) const CREATE_MASTER_EDITION_V3_DISCRIMINATOR: u8 = 17; +pub(crate) const DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR: u8 = 17; /// Set Collection Size discriminator. -pub(crate) const SET_COLLECTION_SIZE_DISCRIMINATOR: u8 = 34; +pub(crate) const DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR: u8 = 34; /// Bubblegum Set Collection Size discriminator. -pub(crate) const BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR: u8 = 36; +pub(crate) const DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR: u8 = 36; /// Create Escrow Account discriminator. -pub(crate) const CREATE_ESCROW_ACCOUNT_DISCRIMINATOR: u8 = 38; +pub(crate) const DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR: u8 = 38; /// Close Escrow Account discriminator. -pub(crate) const CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR: u8 = 39; +pub(crate) const DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR: u8 = 39; /// Transfer Out Of Escrow discriminator. -pub(crate) const TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR: u8 = 40; +pub(crate) const DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR: u8 = 40; /// Collect discriminator. -pub(crate) const COLLECT_DISCRIMINATOR: u8 = 54; +pub(crate) const DC_METADATA_MTM_COLLECT_DISCRIMINATOR: u8 = 54; /// Historical Burn NFT discriminator. -pub(crate) const BURN_NFT_DISCRIMINATOR: u8 = 29; +pub(crate) const DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR: u8 = 29; /// Historical Burn Edition NFT discriminator. -pub(crate) const BURN_EDITION_NFT_DISCRIMINATOR: u8 = 37; +pub(crate) const DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR: u8 = 37; /// Burn discriminator. -pub(crate) const BURN_DISCRIMINATOR: u8 = 41; +pub(crate) const DC_METADATA_MTM_BURN_DISCRIMINATOR: u8 = 41; /// Lock discriminator. -pub(crate) const LOCK_DISCRIMINATOR: u8 = 46; +pub(crate) const DC_METADATA_MTM_LOCK_DISCRIMINATOR: u8 = 46; /// Unlock discriminator. -pub(crate) const UNLOCK_DISCRIMINATOR: u8 = 47; +pub(crate) const DC_METADATA_MTM_UNLOCK_DISCRIMINATOR: u8 = 47; /// Transfer discriminator. -pub(crate) const TRANSFER_DISCRIMINATOR: u8 = 49; +pub(crate) const DC_METADATA_MTM_TRANSFER_DISCRIMINATOR: u8 = 49; /// Close Accounts discriminator. -pub(crate) const CLOSE_ACCOUNTS_DISCRIMINATOR: u8 = 57; +pub(crate) const DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR: u8 = 57; /// Modern Create discriminator. -pub(crate) const CREATE_DISCRIMINATOR: u8 = 42; +pub(crate) const DC_METADATA_MTM_CREATE_DISCRIMINATOR: u8 = 42; /// Modern Mint discriminator. -pub(crate) const MINT_DISCRIMINATOR: u8 = 43; +pub(crate) const DC_METADATA_MTM_MINT_DISCRIMINATOR: u8 = 43; /// Modern Print discriminator. -pub(crate) const PRINT_DISCRIMINATOR: u8 = 55; +pub(crate) const DC_METADATA_MTM_PRINT_DISCRIMINATOR: u8 = 55; /// Modern Update discriminator. -pub(crate) const UPDATE_DISCRIMINATOR: u8 = 50; +pub(crate) const DC_METADATA_MTM_UPDATE_DISCRIMINATOR: u8 = 50; /// Modern Use discriminator. -pub(crate) const USE_DISCRIMINATOR: u8 = 51; +pub(crate) const DC_METADATA_MTM_USE_DISCRIMINATOR: u8 = 51; /// Modern Verify discriminator. -pub(crate) const VERIFY_DISCRIMINATOR: u8 = 52; +pub(crate) const DC_METADATA_MTM_VERIFY_DISCRIMINATOR: u8 = 52; /// Modern Unverify discriminator. -pub(crate) const UNVERIFY_DISCRIMINATOR: u8 = 53; +pub(crate) const DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR: u8 = 53; /// Migrate discriminator. -pub(crate) const MIGRATE_DISCRIMINATOR: u8 = 48; +pub(crate) const DC_METADATA_MTM_MIGRATE_DISCRIMINATOR: u8 = 48; /// Resize discriminator. -pub(crate) const RESIZE_DISCRIMINATOR: u8 = 56; +pub(crate) const DC_METADATA_MTM_RESIZE_DISCRIMINATOR: u8 = 56; /// Delegate discriminator. -pub(crate) const DELEGATE_DISCRIMINATOR: u8 = 44; +pub(crate) const DC_METADATA_MTM_DELEGATE_DISCRIMINATOR: u8 = 44; /// Revoke discriminator. -pub(crate) const REVOKE_DISCRIMINATOR: u8 = 45; +pub(crate) const DC_METADATA_MTM_REVOKE_DISCRIMINATOR: u8 = 45; /// Current pre-release instruction inventory. -pub(crate) const INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ - (CREATE_METADATA_ACCOUNT_DISCRIMINATOR, "create_metadata_account", true), +pub(crate) const DC_METADATA_MTM_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ ( - DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR, + DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR, + "create_metadata_account", + true, + ), + ( + DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR, "deprecated_create_master_edition", true, ), ( - DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR, + DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR, "deprecated_mint_new_edition_from_master_edition_via_printing_token", true, ), - (UPDATE_METADATA_ACCOUNT_DISCRIMINATOR, "update_metadata_account", true), ( - UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR, + DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR, + "update_metadata_account", + true, + ), + ( + DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR, "update_primary_sale_happened_via_token", false, ), ( - DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR, + DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR, "deprecated_set_reservation_list", true, ), ( - DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR, + DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR, "deprecated_create_reservation_list", true, ), - (SIGN_METADATA_DISCRIMINATOR, "sign_metadata", false), + (DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR, "sign_metadata", false), ( - DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR, + DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR, "deprecated_mint_printing_tokens_via_token", true, ), ( - DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR, + DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR, "deprecated_mint_printing_tokens", true, ), - (CREATE_MASTER_EDITION_DISCRIMINATOR, "create_master_edition", true), - (PUFF_METADATA_DISCRIMINATOR, "puff_metadata", false), ( - MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR, + DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR, + "create_master_edition", + true, + ), + (DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR, "puff_metadata", false), + ( + DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR, "mint_new_edition_from_master_edition_via_token", false, ), ( - MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR, + DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR, "mint_new_edition_from_master_edition_via_vault_proxy", true, ), ( - CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR, + DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR, "convert_master_edition_v1_to_v2", true, ), - (UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR, "update_metadata_account_v2", false), - (CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR, "create_metadata_account_v2", true), - (CREATE_MASTER_EDITION_V3_DISCRIMINATOR, "create_master_edition_v3", false), - (CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR, "create_metadata_account_v3", false), - (VERIFY_COLLECTION_DISCRIMINATOR, "verify_collection", false), - (UNVERIFY_COLLECTION_DISCRIMINATOR, "unverify_collection", false), - (SET_AND_VERIFY_COLLECTION_DISCRIMINATOR, "set_and_verify_collection", false), ( - APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR, + DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR, + "update_metadata_account_v2", + false, + ), + ( + DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR, + "create_metadata_account_v2", + true, + ), + ( + DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR, + "create_master_edition_v3", + false, + ), + ( + DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR, + "create_metadata_account_v3", + false, + ), + (DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR, "verify_collection", false), + (DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR, "unverify_collection", false), + ( + DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR, + "set_and_verify_collection", + false, + ), + ( + DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR, "approve_collection_authority", false, ), - (REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR, "revoke_collection_authority", false), ( - VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, + DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR, + "revoke_collection_authority", + false, + ), + ( + DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, "verify_sized_collection_item", false, ), ( - UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, + DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, "unverify_sized_collection_item", false, ), ( - SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, + DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, "set_and_verify_sized_collection_item", false, ), - (UTILIZE_DISCRIMINATOR, "utilize", false), - (APPROVE_USE_AUTHORITY_DISCRIMINATOR, "approve_use_authority", false), - (REVOKE_USE_AUTHORITY_DISCRIMINATOR, "revoke_use_authority", false), - (FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR, "freeze_delegated_account", true), - (THAW_DELEGATED_ACCOUNT_DISCRIMINATOR, "thaw_delegated_account", true), - (REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR, "remove_creator_verification", false), - (SET_TOKEN_STANDARD_DISCRIMINATOR, "set_token_standard", false), - (SET_COLLECTION_SIZE_DISCRIMINATOR, "set_collection_size", false), + (DC_METADATA_MTM_UTILIZE_DISCRIMINATOR, "utilize", false), ( - BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR, + DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR, + "approve_use_authority", + false, + ), + ( + DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR, + "revoke_use_authority", + false, + ), + ( + DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR, + "freeze_delegated_account", + true, + ), + ( + DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR, + "thaw_delegated_account", + true, + ), + ( + DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR, + "remove_creator_verification", + false, + ), + (DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR, "set_token_standard", false), + (DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR, "set_collection_size", false), + ( + DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR, "bubblegum_set_collection_size", false, ), - (CREATE_ESCROW_ACCOUNT_DISCRIMINATOR, "create_escrow_account", false), - (CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR, "close_escrow_account", false), - (TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR, "transfer_out_of_escrow", false), - (BURN_NFT_DISCRIMINATOR, "burn_nft", true), - (BURN_EDITION_NFT_DISCRIMINATOR, "burn_edition_nft", true), - (BURN_DISCRIMINATOR, "burn", false), - (CREATE_DISCRIMINATOR, "create", false), - (MINT_DISCRIMINATOR, "mint", false), - (LOCK_DISCRIMINATOR, "lock", false), - (UNLOCK_DISCRIMINATOR, "unlock", false), - (TRANSFER_DISCRIMINATOR, "transfer", false), - (COLLECT_DISCRIMINATOR, "collect", false), - (PRINT_DISCRIMINATOR, "print", false), - (UPDATE_DISCRIMINATOR, "update", false), - (USE_DISCRIMINATOR, "use", false), - (VERIFY_DISCRIMINATOR, "verify", false), - (UNVERIFY_DISCRIMINATOR, "unverify", false), - (MIGRATE_DISCRIMINATOR, "migrate", false), - (RESIZE_DISCRIMINATOR, "resize", false), - (CLOSE_ACCOUNTS_DISCRIMINATOR, "close_accounts", false), - (DELEGATE_DISCRIMINATOR, "delegate", false), - (REVOKE_DISCRIMINATOR, "revoke", false), + ( + DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR, + "create_escrow_account", + false, + ), + ( + DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR, + "close_escrow_account", + false, + ), + ( + DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR, + "transfer_out_of_escrow", + false, + ), + (DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR, "burn_nft", true), + (DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR, "burn_edition_nft", true), + (DC_METADATA_MTM_BURN_DISCRIMINATOR, "burn", false), + (DC_METADATA_MTM_CREATE_DISCRIMINATOR, "create", false), + (DC_METADATA_MTM_MINT_DISCRIMINATOR, "mint", false), + (DC_METADATA_MTM_LOCK_DISCRIMINATOR, "lock", false), + (DC_METADATA_MTM_UNLOCK_DISCRIMINATOR, "unlock", false), + (DC_METADATA_MTM_TRANSFER_DISCRIMINATOR, "transfer", false), + (DC_METADATA_MTM_COLLECT_DISCRIMINATOR, "collect", false), + (DC_METADATA_MTM_PRINT_DISCRIMINATOR, "print", false), + (DC_METADATA_MTM_UPDATE_DISCRIMINATOR, "update", false), + (DC_METADATA_MTM_USE_DISCRIMINATOR, "use", false), + (DC_METADATA_MTM_VERIFY_DISCRIMINATOR, "verify", false), + (DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR, "unverify", false), + (DC_METADATA_MTM_MIGRATE_DISCRIMINATOR, "migrate", false), + (DC_METADATA_MTM_RESIZE_DISCRIMINATOR, "resize", false), + (DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR, "close_accounts", false), + (DC_METADATA_MTM_DELEGATE_DISCRIMINATOR, "delegate", false), + (DC_METADATA_MTM_REVOKE_DISCRIMINATOR, "revoke", false), ]; /// Canonical tracing target for this decoder. -pub(crate) const TRACING_TARGET: &str = "kb-lib.decoder.metadata.metaplex_token_metadata"; +pub(crate) const DC_METADATA_MTM_TRACING_TARGET: &str = + "kb-lib.decoder.metadata.metaplex_token_metadata"; diff --git a/kb-lib/src/decoder/metadata/metaplex_token_metadata/decoder.rs b/kb-lib/src/decoder/metadata/metaplex_token_metadata/decoder.rs index abd637f..b9080cf 100644 --- a/kb-lib/src/decoder/metadata/metaplex_token_metadata/decoder.rs +++ b/kb-lib/src/decoder/metadata/metaplex_token_metadata/decoder.rs @@ -3,9 +3,9 @@ //! Exact contextual dispatch for Metaplex Token Metadata. -const SURFACES: &[crate::DecoderSurface] = &[crate::DecoderSurface { +const SURFACES: &[crate::DcApiDecoderSurface] = &[crate::DcApiDecoderSurface { program_id: kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, - surface_code: crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE, + surface_code: crate::DC_METADATA_MTM_SURFACE_CODE, priority: 100, }]; @@ -13,11 +13,9 @@ const PROGRAM_IDS: &[&str] = &[kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_ /// Exact decoder for the Metaplex Token Metadata program. #[derive(Clone, Debug, Default)] -pub struct MetadataMetaplexTokenMetadataDecoder; +pub struct DcMetadataMetaplexTokenMetadataDecoder; -impl crate::ProtocolDecoder - for crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder -{ +impl crate::DcApiProtocolDecoder for crate::DcMetadataMetaplexTokenMetadataDecoder { fn decoder_name(&self) -> &'static str { return "kb_decoder_metadata_metaplex_token_metadata"; } @@ -32,48 +30,46 @@ impl crate::ProtocolDecoder fn supports_observation( &self, - observation: &crate::ProgramObservation, - ) -> crate::DecoderSupport { - return if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) { - crate::DecoderSupport::Yes + observation: &crate::MdProgramObservation, + ) -> crate::DcApiDecoderSupport { + return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + crate::DcApiDecoderSupport::Yes } else { - crate::DecoderSupport::No + crate::DcApiDecoderSupport::No }; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::InstructionDecoder - for crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder -{ - fn identity(&self) -> crate::DecoderIdentity { - return crate::DecoderIdentity { - name: crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE.to_string(), +impl crate::DcApiInstructionDecoder for crate::DcMetadataMetaplexTokenMetadataDecoder { + fn identity(&self) -> crate::DcApiDecoderIdentity { + return crate::DcApiDecoderIdentity { + name: crate::DC_METADATA_MTM_SURFACE_CODE.to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn surfaces(&self) -> &'static [crate::DecoderSurface] { + fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] { return SURFACES; } - fn coverage(&self) -> std::vec::Vec { - return crate::decoder::metadata::metaplex_token_metadata::INSTRUCTION_ENTRIES + fn coverage(&self) -> std::vec::Vec { + return crate::DC_METADATA_MTM_INSTRUCTION_ENTRIES .iter() .map(|(discriminator, code, historical)| { - return crate::DecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID .to_string(), surface_code: std::option::Option::Some( - crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE.to_string(), + crate::DC_METADATA_MTM_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: (*code).to_string(), discriminator_hex: std::option::Option::Some(format!("{discriminator:02x}")), historical: *historical, @@ -82,42 +78,47 @@ impl crate::InstructionDecoder .collect(); } - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition { + fn recognize( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderRecognition { if input.program_id != kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID { - return crate::DecoderRecognition::incompatible(); + return crate::DcApiDecoderRecognition::incompatible(); } let discriminator = - crate::decoder::metadata::metaplex_token_metadata::payload_discriminator(input); + crate::decoder_metadata_metaplex_token_metadata_payload_discriminator(input); let entry = discriminator - .and_then(crate::decoder::metadata::metaplex_token_metadata::entry_for_discriminator); - return crate::DecoderRecognition::compatible( + .and_then(crate::decoder_metadata_metaplex_token_metadata_entry_for_discriminator); + return crate::DcApiDecoderRecognition::compatible( entry.is_some(), 100, - std::option::Option::Some( - crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE.to_string(), - ), + std::option::Option::Some(crate::DC_METADATA_MTM_SURFACE_CODE.to_string()), entry.map(|(_, code, _)| return code.to_string()), discriminator.map(|value| return format!("{value:02x}")), ); } - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { + fn decode( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderExecutionResult { if input.program_id != kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID { - return crate::DecoderExecutionResult::unsupported(std::option::Option::None); + return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None); } - let result = crate::decoder::metadata::metaplex_token_metadata::decode(input); + let result = crate::decoder_metadata_metaplex_token_metadata_decode(input); if matches!( result.status, - crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported + crate::DcApiDecoderOutcomeStatus::Failed + | crate::DcApiDecoderOutcomeStatus::Unsupported ) { tracing::error!( - target: crate::decoder::metadata::metaplex_token_metadata::TRACING_TARGET, + target: crate::DC_METADATA_MTM_TRACING_TARGET, action = "decode_failure", signature = %input.signature, slot = input.slot, instruction_path = %input.instruction_path, program_id = %input.program_id, - processor_name = crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE, + processor_name = crate::DC_METADATA_MTM_SURFACE_CODE, processor_version = env!("CARGO_PKG_VERSION"), input_key = %input.replay_input_key, result_status = ?result.status, @@ -126,7 +127,7 @@ impl crate::InstructionDecoder ); } tracing::debug!( - target: crate::decoder::metadata::metaplex_token_metadata::TRACING_TARGET, + target: crate::DC_METADATA_MTM_TRACING_TARGET, action = "decode", signature = %input.signature, instruction_path = %input.instruction_path, @@ -155,7 +156,7 @@ mod tests { account_count: usize, failed: bool, path: &str, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let keys = (0..account_count).map(|position| return serde_json::json!({ "accountIndex": position, "accountKey": format!("account{position}"), @@ -171,7 +172,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{path}"), "signature", 42, @@ -205,7 +206,7 @@ mod tests { flags: &[(bool, bool)], failed: bool, path: &str, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let keys = flags .iter() .enumerate() @@ -229,7 +230,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{path}"), "signature", 42, @@ -280,7 +281,7 @@ mod tests { is_mutable: true, collection_details: std::option::Option::None, }; - let mut wire = std::vec![crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR]; let encoded = borsh_0_10::to_vec(&args); match encoded { std::result::Result::Ok(mut value) => wire.append(&mut value), @@ -298,7 +299,7 @@ mod tests { primary_sale_happened: std::option::Option::Some(true), is_mutable: std::option::Option::Some(false), }; - let mut wire = std::vec![crate::decoder::metadata::metaplex_token_metadata::UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR]; let encoded = borsh_0_10::to_vec(&args); match encoded { std::result::Result::Ok(mut value) => wire.append(&mut value), @@ -312,9 +313,7 @@ mod tests { fn approve_use_authority_wire(number_of_uses: u64) -> std::vec::Vec { let args = mpl_token_metadata::instructions::ApproveUseAuthorityInstructionArgs { number_of_uses }; - let mut wire = std::vec![ - crate::decoder::metadata::metaplex_token_metadata::APPROVE_USE_AUTHORITY_DISCRIMINATOR - ]; + let mut wire = std::vec![crate::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR]; let encoded = borsh_0_10::to_vec(&args); match encoded { std::result::Result::Ok(mut value) => wire.append(&mut value), @@ -325,8 +324,7 @@ mod tests { fn utilize_wire(number_of_uses: u64) -> std::vec::Vec { let args = mpl_token_metadata::instructions::UtilizeInstructionArgs { number_of_uses }; - let mut wire = - std::vec![crate::decoder::metadata::metaplex_token_metadata::UTILIZE_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_UTILIZE_DISCRIMINATOR]; let encoded = borsh_0_10::to_vec(&args); match encoded { std::result::Result::Ok(mut value) => wire.append(&mut value), @@ -346,7 +344,7 @@ mod tests { } fn historical_create_v1_wire() -> std::vec::Vec { - let mut wire = std::vec![crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR]; match borsh_0_10::to_vec(&historical_data()) { std::result::Result::Ok(mut value) => wire.append(&mut value), std::result::Result::Err(error) => { @@ -363,7 +361,7 @@ mod tests { } fn historical_update_v1_wire() -> std::vec::Vec { - let mut wire = std::vec![crate::decoder::metadata::metaplex_token_metadata::UPDATE_METADATA_ACCOUNT_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR]; let data = std::option::Option::Some(historical_data()); let authority = std::option::Option::Some([7_u8; 32]); let primary_sale = std::option::Option::Some(true); @@ -392,7 +390,7 @@ mod tests { collection: std::option::Option::None, uses: std::option::Option::None, }; - let mut wire = std::vec![crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR]; let encoded_data = borsh_0_10::to_vec(&data); match encoded_data { std::result::Result::Ok(mut value) => wire.append(&mut value), @@ -425,7 +423,7 @@ mod tests { } fn create_master_edition_v3_wire(max_supply: std::option::Option) -> std::vec::Vec { - let mut wire = std::vec![crate::decoder::metadata::metaplex_token_metadata::CREATE_MASTER_EDITION_V3_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR]; let encoded = borsh_0_10::to_vec(&max_supply); match encoded { std::result::Result::Ok(mut value) => wire.append(&mut value), @@ -465,8 +463,7 @@ mod tests { } fn delegate_wire(args: &mpl_token_metadata::types::DelegateArgs) -> std::vec::Vec { - let mut wire = - std::vec![crate::decoder::metadata::metaplex_token_metadata::DELEGATE_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_DELEGATE_DISCRIMINATOR]; let encoded = match borsh_0_10::BorshSerialize::try_to_vec(args) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { @@ -478,8 +475,7 @@ mod tests { } fn revoke_wire(args: &mpl_token_metadata::types::RevokeArgs) -> std::vec::Vec { - let mut wire = - std::vec![crate::decoder::metadata::metaplex_token_metadata::REVOKE_DISCRIMINATOR]; + let mut wire = std::vec![crate::DC_METADATA_MTM_REVOKE_DISCRIMINATOR]; let encoded = match borsh_0_10::BorshSerialize::try_to_vec(args) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { @@ -492,32 +488,30 @@ mod tests { #[test] fn decoder_identity_program_boundary_and_coverage_are_exact() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; assert_eq!( - crate::ProtocolDecoder::decoder_name(&decoder), + crate::DcApiProtocolDecoder::decoder_name(&decoder), "kb_decoder_metadata_metaplex_token_metadata" ); assert_eq!( - crate::ProtocolDecoder::program_ids(&decoder), + crate::DcApiProtocolDecoder::program_ids(&decoder), &[kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID] ); assert_eq!( - crate::decoder::metadata::metaplex_token_metadata::TRACING_TARGET, + crate::DC_METADATA_MTM_TRACING_TARGET, "kb-lib.decoder.metadata.metaplex_token_metadata" ); - assert_eq!(crate::InstructionDecoder::coverage(&decoder).len(), 58); + assert_eq!(crate::DcApiInstructionDecoder::coverage(&decoder).len(), 58); } #[test] fn printed_edition_mint_variants_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let token = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let token = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( mint_new_edition_wire( - crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR, + crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR, u64::MAX, ) .as_slice(), @@ -540,18 +534,18 @@ mod tests { "printed_edition_token", ), ); - assert_eq!(token.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(token.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( token.recognized_entry_code.as_deref(), std::option::Option::Some("mint_new_edition_from_master_edition_via_token") ); assert_eq!(token.observations[0].payload_json["parameters"]["edition"], u64::MAX); assert_eq!(token.observations[0].payload_json["accounts"][4]["role"], "edition_marker"); - let vault = crate::InstructionDecoder::decode( + let vault = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( mint_new_edition_wire( - crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR, + crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR, 248, ) .as_slice(), @@ -577,7 +571,7 @@ mod tests { "printed_edition_vault", ), ); - assert_eq!(vault.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(vault.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( vault.recognized_entry_code.as_deref(), std::option::Option::Some("mint_new_edition_from_master_edition_via_vault_proxy") @@ -607,17 +601,13 @@ mod tests { decimals: std::option::Option::None, print_supply: std::option::Option::None, }; - return programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::CREATE_DISCRIMINATOR, - &args, - ); + return programmable_wire(crate::DC_METADATA_MTM_CREATE_DISCRIMINATOR, &args); } #[test] fn modern_create_decodes_exact_contract() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let result = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let result = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_create_wire().as_slice(), @@ -636,7 +626,7 @@ mod tests { "modern_create", ), ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some("create")); assert_eq!(result.observations[0].payload_json["accounts"][0]["role"], "metadata"); assert_eq!( @@ -647,12 +637,11 @@ mod tests { #[test] fn modern_create_rejects_truncated_invalid_and_suffix_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CREATE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CREATE_DISCRIMINATOR], &[ (false, true), (false, true), @@ -668,8 +657,8 @@ mod tests { "modern_create_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_create_wire().as_slice(), @@ -688,10 +677,10 @@ mod tests { "modern_create_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut suffix_wire = modern_create_wire(); suffix_wire.push(1); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( suffix_wire.as_slice(), @@ -710,7 +699,7 @@ mod tests { "modern_create_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } fn modern_mint_wire(amount: u64) -> std::vec::Vec { @@ -718,17 +707,13 @@ mod tests { amount, authorization_data: std::option::Option::None, }; - return programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::MINT_DISCRIMINATOR, - &args, - ); + return programmable_wire(crate::DC_METADATA_MTM_MINT_DISCRIMINATOR, &args); } #[test] fn modern_mint_decodes_exact_contract() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let result = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let result = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_mint_wire(u64::MAX).as_slice(), @@ -753,7 +738,7 @@ mod tests { "modern_mint", ), ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some("mint")); assert_eq!(result.observations[0].payload_json["parameters"]["V1"]["amount"], u64::MAX); assert_eq!(result.observations[0].payload_json["accounts"][4]["role"], "token_record"); @@ -765,8 +750,7 @@ mod tests { #[test] fn modern_mint_rejects_truncated_invalid_and_suffix_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = [ (false, true), (false, false), @@ -784,19 +768,19 @@ mod tests { (false, false), (false, false), ]; - let truncated = crate::InstructionDecoder::decode( + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::MINT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_MINT_DISCRIMINATOR], &flags, false, "modern_mint_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut invalid_flags = flags; invalid_flags[6] = (false, false); - let invalid = crate::InstructionDecoder::decode( + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_mint_wire(1).as_slice(), @@ -805,36 +789,29 @@ mod tests { "modern_mint_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut suffix_wire = modern_mint_wire(2); suffix_wire.push(1); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(suffix_wire.as_slice(), &flags, false, "modern_mint_suffix"), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } fn modern_print_wire_v1(edition: u64) -> std::vec::Vec { let args = mpl_token_metadata::types::PrintArgs::V1 { edition }; - return programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::PRINT_DISCRIMINATOR, - &args, - ); + return programmable_wire(crate::DC_METADATA_MTM_PRINT_DISCRIMINATOR, &args); } fn modern_print_wire_v2(edition: u64) -> std::vec::Vec { let args = mpl_token_metadata::types::PrintArgs::V2 { edition }; - return programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::PRINT_DISCRIMINATOR, - &args, - ); + return programmable_wire(crate::DC_METADATA_MTM_PRINT_DISCRIMINATOR, &args); } #[test] fn modern_print_v1_and_v2_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = [ (false, true), (false, true), @@ -855,7 +832,7 @@ mod tests { (false, false), (false, false), ]; - let v1 = crate::InstructionDecoder::decode( + let v1 = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_print_wire_v1(u64::MAX).as_slice(), @@ -864,23 +841,22 @@ mod tests { "modern_print_v1", ), ); - assert_eq!(v1.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(v1.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(v1.recognized_entry_code.as_deref(), std::option::Option::Some("print")); assert_eq!(v1.observations[0].payload_json["parameters"]["V1"]["edition"], u64::MAX); assert_eq!(v1.observations[0].payload_json["accounts"][8]["role"], "edition_marker_pda"); - let v2 = crate::InstructionDecoder::decode( + let v2 = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(modern_print_wire_v2(42).as_slice(), &flags, true, "modern_print_v2"), ); - assert_eq!(v2.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(v2.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(v2.observations[0].payload_json["parameters"]["V2"]["edition"], 42); assert!(!v2.observations[0].observation_committed); } #[test] fn modern_print_rejects_truncated_invalid_and_suffix_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = [ (false, true), (false, true), @@ -901,19 +877,19 @@ mod tests { (false, false), (false, false), ]; - let truncated = crate::InstructionDecoder::decode( + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::PRINT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_PRINT_DISCRIMINATOR], &flags, false, "modern_print_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut invalid_flags = flags; invalid_flags[10] = (false, false); - let invalid = crate::InstructionDecoder::decode( + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_print_wire_v1(1).as_slice(), @@ -922,14 +898,14 @@ mod tests { "modern_print_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut suffix_wire = modern_print_wire_v2(2); suffix_wire.push(1); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(suffix_wire.as_slice(), &flags, false, "modern_print_suffix"), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } fn modern_update_wire() -> std::vec::Vec { @@ -937,16 +913,12 @@ mod tests { collection: mpl_token_metadata::types::CollectionToggle::None, authorization_data: std::option::Option::None, }; - return programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::UPDATE_DISCRIMINATOR, - &args, - ); + return programmable_wire(crate::DC_METADATA_MTM_UPDATE_DISCRIMINATOR, &args); } #[test] fn modern_update_variants_decode_exact_contract() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = [ (true, false), (false, false), @@ -960,11 +932,11 @@ mod tests { (false, false), (false, false), ]; - let result = crate::InstructionDecoder::decode( + let result = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(modern_update_wire().as_slice(), &flags, false, "modern_update"), ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some("update")); assert_eq!( result.observations[0].payload_json["parameters"]["AsCollectionDelegateV2"]["collection"], @@ -979,8 +951,7 @@ mod tests { #[test] fn modern_update_rejects_truncated_invalid_and_suffix_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = [ (true, false), (false, false), @@ -994,19 +965,19 @@ mod tests { (false, false), (false, false), ]; - let truncated = crate::InstructionDecoder::decode( + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::UPDATE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_UPDATE_DISCRIMINATOR], &flags, false, "modern_update_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut invalid_flags = flags; invalid_flags[0] = (false, false); - let invalid = crate::InstructionDecoder::decode( + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_update_wire().as_slice(), @@ -1015,24 +986,21 @@ mod tests { "modern_update_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut suffix_wire = modern_update_wire(); suffix_wire.push(1); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(suffix_wire.as_slice(), &flags, false, "modern_update_suffix"), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } fn modern_use_wire() -> std::vec::Vec { let args = mpl_token_metadata::types::UseArgs::V1 { authorization_data: std::option::Option::None, }; - return programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::USE_DISCRIMINATOR, - &args, - ); + return programmable_wire(crate::DC_METADATA_MTM_USE_DISCRIMINATOR, &args); } fn modern_verification_wire( @@ -1044,8 +1012,7 @@ mod tests { #[test] fn modern_use_verify_and_unverify_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let use_flags = [ (true, false), (false, true), @@ -1060,11 +1027,11 @@ mod tests { (false, false), (false, false), ]; - let use_result = crate::InstructionDecoder::decode( + let use_result = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(modern_use_wire().as_slice(), &use_flags, false, "modern_use"), ); - assert_eq!(use_result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(use_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(use_result.recognized_entry_code.as_deref(), std::option::Option::Some("use")); assert_eq!( use_result.observations[0].payload_json["parameters"]["V1"]["authorization_data"], @@ -1080,11 +1047,11 @@ mod tests { (false, false), (false, false), ]; - let verify = crate::InstructionDecoder::decode( + let verify = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_verification_wire( - crate::decoder::metadata::metaplex_token_metadata::VERIFY_DISCRIMINATOR, + crate::DC_METADATA_MTM_VERIFY_DISCRIMINATOR, mpl_token_metadata::types::VerificationArgs::CollectionV1, ) .as_slice(), @@ -1093,13 +1060,13 @@ mod tests { "modern_verify", ), ); - assert_eq!(verify.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(verify.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(verify.observations[0].payload_json["parameters"], "CollectionV1"); - let unverify = crate::InstructionDecoder::decode( + let unverify = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_verification_wire( - crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_DISCRIMINATOR, + crate::DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR, mpl_token_metadata::types::VerificationArgs::CreatorV1, ) .as_slice(), @@ -1108,7 +1075,7 @@ mod tests { "modern_unverify", ), ); - assert_eq!(unverify.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(unverify.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( unverify.recognized_entry_code.as_deref(), std::option::Option::Some("unverify") @@ -1118,8 +1085,7 @@ mod tests { #[test] fn modern_use_verify_and_unverify_reject_invalid_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let use_flags = [ (true, false), (false, true), @@ -1134,19 +1100,19 @@ mod tests { (false, false), (false, false), ]; - let truncated = crate::InstructionDecoder::decode( + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::USE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_USE_DISCRIMINATOR], &use_flags, false, "modern_use_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut invalid_flags = use_flags; invalid_flags[0] = (false, false); - let invalid = crate::InstructionDecoder::decode( + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( modern_use_wire().as_slice(), @@ -1155,7 +1121,7 @@ mod tests { "modern_use_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); let verify_flags = [ (true, false), (false, false), @@ -1167,36 +1133,35 @@ mod tests { (false, false), ]; let mut suffix_wire = modern_verification_wire( - crate::decoder::metadata::metaplex_token_metadata::VERIFY_DISCRIMINATOR, + crate::DC_METADATA_MTM_VERIFY_DISCRIMINATOR, mpl_token_metadata::types::VerificationArgs::CreatorV1, ); suffix_wire.push(1); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(suffix_wire.as_slice(), &verify_flags, false, "modern_verify_suffix"), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn printed_edition_mint_variants_reject_truncated_wire_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR], &[(false, true); 13], false, "printed_edition_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( mint_new_edition_wire( - crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR, + crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR, 1, ) .as_slice(), @@ -1219,13 +1184,13 @@ mod tests { "printed_edition_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut suffix_wire = mint_new_edition_wire( - crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR, + crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR, 2, ); suffix_wire.push(1); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( suffix_wire.as_slice(), @@ -1251,14 +1216,13 @@ mod tests { "printed_edition_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn master_edition_creation_and_conversion_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let create = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let create = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( create_master_edition_v3_wire(std::option::Option::Some(u64::MAX)).as_slice(), @@ -1276,23 +1240,23 @@ mod tests { "master_edition_create", ), ); - assert_eq!(create.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(create.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( create.recognized_entry_code.as_deref(), std::option::Option::Some("create_master_edition_v3") ); assert_eq!(create.observations[0].payload_json["parameters"]["max_supply"], u64::MAX); assert_eq!(create.observations[0].payload_json["accounts"][0]["role"], "master_edition"); - let convert = crate::InstructionDecoder::decode( + let convert = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR], &[(false, true), (false, true), (false, true)], true, "master_edition_convert", ), ); - assert_eq!(convert.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(convert.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( convert.recognized_entry_code.as_deref(), std::option::Option::Some("convert_master_edition_v1_to_v2") @@ -1302,12 +1266,11 @@ mod tests { #[test] fn master_edition_group_rejects_truncated_wire_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CREATE_MASTER_EDITION_V3_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR], &[ (false, true), (false, true), @@ -1322,8 +1285,8 @@ mod tests { "master_edition_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( create_master_edition_v3_wire(std::option::Option::None).as_slice(), @@ -1341,24 +1304,23 @@ mod tests { "master_edition_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR, 1], + &[crate::DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR, 1], &[(false, true), (false, true), (false, true)], false, "master_edition_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn historical_v1_create_and_update_decode_exact_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let create = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let create = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( historical_create_v1_wire().as_slice(), @@ -1375,13 +1337,13 @@ mod tests { "legacy_create_v1", ), ); - assert_eq!(create.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(create.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( create.recognized_entry_code.as_deref(), std::option::Option::Some("create_metadata_account") ); assert_eq!(create.observations[0].payload_json["parameters"]["data"]["name"], "Legacy V1"); - let update = crate::InstructionDecoder::decode( + let update = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( historical_update_v1_wire().as_slice(), @@ -1390,7 +1352,7 @@ mod tests { "legacy_update_v1", ), ); - assert_eq!(update.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(update.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( update.recognized_entry_code.as_deref(), std::option::Option::Some("update_metadata_account") @@ -1404,19 +1366,18 @@ mod tests { #[test] fn historical_v1_wires_reject_truncation_and_invalid_accounts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::UPDATE_METADATA_ACCOUNT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR], &[(false, true), (true, false)], false, "legacy_update_v1_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( historical_create_v1_wire().as_slice(), @@ -1433,14 +1394,13 @@ mod tests { "legacy_create_v1_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn historical_create_metadata_account_v2_decodes_bounded_data_v2() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let result = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let result = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( historical_create_v2_wire().as_slice(), @@ -1457,7 +1417,7 @@ mod tests { "legacy_create_v2", ), ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("create_metadata_account_v2") @@ -1471,12 +1431,11 @@ mod tests { #[test] fn historical_create_metadata_account_v2_rejects_truncated_wire_and_invalid_flags() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR], &[ (false, true), (false, false), @@ -1489,8 +1448,8 @@ mod tests { "legacy_create_v2_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( historical_create_v2_wire().as_slice(), @@ -1506,18 +1465,17 @@ mod tests { "legacy_create_v2_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn create_metadata_account_v3_decodes_official_borsh_wire() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let result = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let result = crate::DcApiInstructionDecoder::decode( &decoder, &input(create_wire().as_slice(), 6, false, "0"), ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("create_metadata_account_v3") @@ -1529,16 +1487,15 @@ mod tests { #[test] fn update_metadata_account_v2_preserves_failed_transaction_as_uncommitted() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let result = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let result = crate::DcApiInstructionDecoder::decode( &decoder, &input(update_wire().as_slice(), 2, true, "1/0"), ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.observations[0].event.source_kind, - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction ); assert!(!result.observations[0].observation_committed); assert_eq!( @@ -1549,12 +1506,11 @@ mod tests { #[test] fn collection_verification_family_decodes_exact_account_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let verify = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let verify = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::VERIFY_COLLECTION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR], &[ (false, true), (true, true), @@ -1568,7 +1524,7 @@ mod tests { "2/0", ), ); - assert_eq!(verify.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(verify.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( verify.recognized_entry_code.as_deref(), std::option::Option::Some("verify_collection") @@ -1577,21 +1533,21 @@ mod tests { verify.observations[0].payload_json["accounts"][6]["role"], "collection_authority_record" ); - let unverify = crate::InstructionDecoder::decode( + let unverify = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_COLLECTION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR], &[(false, true), (true, true), (false, false), (false, false), (false, false)], true, "2/1", ), ); - assert_eq!(unverify.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(unverify.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!unverify.observations[0].observation_committed); - let set_and_verify = crate::InstructionDecoder::decode( + let set_and_verify = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::SET_AND_VERIFY_COLLECTION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR], &[ (false, true), (true, true), @@ -1606,7 +1562,7 @@ mod tests { "3", ), ); - assert_eq!(set_and_verify.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(set_and_verify.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( set_and_verify.observations[0].payload_json["accounts"][3]["role"], "update_authority" @@ -1615,12 +1571,11 @@ mod tests { #[test] fn collection_authority_administration_decodes_exact_account_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let approve = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let approve = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR], &[ (false, true), (false, false), @@ -1635,7 +1590,7 @@ mod tests { "approve_collection_authority", ), ); - assert_eq!(approve.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(approve.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( approve.recognized_entry_code.as_deref(), std::option::Option::Some("approve_collection_authority") @@ -1649,16 +1604,16 @@ mod tests { "new_collection_authority" ); assert_eq!(approve.observations[0].payload_json["accounts"][7]["role"], "rent"); - let revoke = crate::InstructionDecoder::decode( + let revoke = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR], &[(false, true), (false, true), (true, true), (false, false), (false, false)], true, "4/0", ), ); - assert_eq!(revoke.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(revoke.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!revoke.observations[0].observation_committed); assert_eq!( revoke.observations[0].payload_json["accounts"][1]["role"], @@ -1669,12 +1624,11 @@ mod tests { #[test] fn collection_authority_administration_rejects_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR], &[ (false, true), (false, false), @@ -1688,24 +1642,23 @@ mod tests { "approve-invalid-flags", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR, 0], &[(false, true), (false, true), (true, true), (false, false), (false, false)], false, "revoke-suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn use_authority_family_decodes_parameters_and_exact_account_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let approve = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let approve = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( approve_use_authority_wire(u64::MAX).as_slice(), @@ -1726,7 +1679,7 @@ mod tests { "approve_use_authority", ), ); - assert_eq!(approve.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(approve.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(approve.observations[0].payload_json["parameters"]["number_of_uses"], u64::MAX); assert_eq!( approve.observations[0].payload_json["accounts"][0]["role"], @@ -1734,10 +1687,10 @@ mod tests { ); assert_eq!(approve.observations[0].payload_json["accounts"][7]["role"], "burner"); assert_eq!(approve.observations[0].payload_json["accounts"][10]["role"], "rent"); - let revoke = crate::InstructionDecoder::decode( + let revoke = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::REVOKE_USE_AUTHORITY_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR], &[ (false, true), (true, true), @@ -1753,13 +1706,13 @@ mod tests { "revoke_use_authority/0", ), ); - assert_eq!(revoke.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(revoke.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!revoke.observations[0].observation_committed); assert_eq!( revoke.observations[0].payload_json["accounts"][3]["role"], "owner_token_account" ); - let utilize = crate::InstructionDecoder::decode( + let utilize = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( utilize_wire(3).as_slice(), @@ -1780,7 +1733,7 @@ mod tests { "utilize", ), ); - assert_eq!(utilize.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(utilize.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(utilize.observations[0].payload_json["parameters"]["number_of_uses"], 3); assert_eq!( utilize.observations[0].payload_json["accounts"][9]["role"], @@ -1791,19 +1744,18 @@ mod tests { #[test] fn use_authority_family_rejects_truncated_wire_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::APPROVE_USE_AUTHORITY_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR], &[(false, true); 10], false, "approve_use_authority_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid_flags = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid_flags = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( utilize_wire(1).as_slice(), @@ -1822,11 +1774,11 @@ mod tests { "utilize_invalid_flags", ), ); - assert_eq!(invalid_flags.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid_flags.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::REVOKE_USE_AUTHORITY_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR, 0], &[ (false, true), (true, true), @@ -1841,35 +1793,34 @@ mod tests { "revoke_use_authority_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn creator_signature_and_primary_sale_family_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let sign = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let sign = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::SIGN_METADATA_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR], &[(false, true), (true, false)], false, "sign_metadata", ), ); - assert_eq!(sign.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(sign.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(sign.observations[0].payload_json["accounts"][0]["role"], "metadata"); assert_eq!(sign.observations[0].payload_json["accounts"][1]["role"], "creator"); - let primary_sale = crate::InstructionDecoder::decode( + let primary_sale = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR], &[(false, true), (true, false), (false, false)], true, "update_primary_sale_happened_via_token/0", ), ); - assert_eq!(primary_sale.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(primary_sale.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!primary_sale.observations[0].observation_committed); assert_eq!(primary_sale.observations[0].payload_json["accounts"][1]["role"], "owner"); assert_eq!( @@ -1880,34 +1831,32 @@ mod tests { #[test] fn creator_signature_and_primary_sale_family_reject_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::SIGN_METADATA_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR], &[(false, true), (false, false)], false, "sign_metadata_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR, 0], &[(false, true), (true, false), (false, false)], false, "primary_sale_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn sized_collection_verification_family_preserves_writable_collection_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = &[ (false, true), (true, false), @@ -1919,19 +1868,19 @@ mod tests { ]; for (discriminator, code) in [ ( - crate::decoder::metadata::metaplex_token_metadata::VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, + crate::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, "verify_sized_collection_item", ), ( - crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, + crate::DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, "unverify_sized_collection_item", ), ] { - let result = crate::InstructionDecoder::decode( + let result = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(&[discriminator], flags, false, code), ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some(code)); assert_eq!( result.observations[0].payload_json["accounts"][4]["role"], @@ -1943,10 +1892,10 @@ mod tests { "collection_authority_record" ); } - let set_and_verify = crate::InstructionDecoder::decode( + let set_and_verify = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR], &[ (false, true), (true, false), @@ -1961,7 +1910,7 @@ mod tests { "set_and_verify_sized_collection_item", ), ); - assert_eq!(set_and_verify.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(set_and_verify.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!set_and_verify.observations[0].observation_committed); assert_eq!( set_and_verify.observations[0].payload_json["accounts"][3]["role"], @@ -1972,12 +1921,11 @@ mod tests { #[test] fn sized_collection_verification_rejects_non_writable_collection_and_suffix() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid_collection = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid_collection = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR], &[ (false, true), (true, false), @@ -1990,11 +1938,11 @@ mod tests { "sized-invalid-flags", ), ); - assert_eq!(invalid_collection.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid_collection.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR, 0], &[ (false, true), (true, false), @@ -2007,17 +1955,16 @@ mod tests { "sized-suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn collection_verification_rejects_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid_flags = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid_flags = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::VERIFY_COLLECTION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2030,40 +1977,47 @@ mod tests { "4", ), ); - assert_eq!(invalid_flags.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid_flags.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_COLLECTION_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR, 0], &[(false, true), (true, true), (false, false), (false, false), (false, false)], false, "5", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn unknown_truncated_suffix_and_invalid_accounts_fail_closed() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let unknown = crate::InstructionDecoder::decode(&decoder, &input(&[254], 0, false, "0")); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let unknown = + crate::DcApiInstructionDecoder::decode(&decoder, &input(&[254], 0, false, "0")); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, - &input(&[crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR], 6, false, "0"), + &input( + &[crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR], + 6, + false, + "0", + ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut suffix = update_wire(); suffix.push(7); - let suffix_result = - crate::InstructionDecoder::decode(&decoder, &input(suffix.as_slice(), 2, false, "0")); - assert_eq!(suffix_result.status, crate::DecoderOutcomeStatus::Failed); - let accounts = crate::InstructionDecoder::decode( + let suffix_result = crate::DcApiInstructionDecoder::decode( + &decoder, + &input(suffix.as_slice(), 2, false, "0"), + ); + assert_eq!(suffix_result.status, crate::DcApiDecoderOutcomeStatus::Failed); + let accounts = crate::DcApiInstructionDecoder::decode( &decoder, &input(create_wire().as_slice(), 2, false, "0"), ); - assert_eq!(accounts.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(accounts.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] @@ -2095,114 +2049,114 @@ mod tests { #[test] fn metadata_normalization_and_creator_unverification_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let puff = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let puff = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::PUFF_METADATA_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR], &[(false, true)], false, "puff_metadata", ), ); - assert_eq!(puff.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(puff.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(puff.observations[0].payload_json["accounts"][0]["role"], "metadata"); - let remove = crate::InstructionDecoder::decode( + let remove = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR], &[(false, true), (true, false)], true, "remove_creator_verification/0", ), ); - assert_eq!(remove.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(remove.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!remove.observations[0].observation_committed); assert_eq!(remove.observations[0].payload_json["accounts"][1]["role"], "creator"); - let token_standard = crate::InstructionDecoder::decode( + let token_standard = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::SET_TOKEN_STANDARD_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR], &[(false, true), (true, false), (false, false), (false, false)], false, "set_token_standard", ), ); - assert_eq!(token_standard.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(token_standard.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(token_standard.observations[0].payload_json["accounts"][3]["role"], "edition"); } #[test] fn metadata_normalization_family_rejects_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR], &[(false, true), (false, false)], false, "remove_creator_verification_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[ - crate::decoder::metadata::metaplex_token_metadata::PUFF_METADATA_DISCRIMINATOR, - 0, - ], + &[crate::DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR, 0], &[(false, true)], false, "puff_metadata_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); - let invalid_standard = crate::InstructionDecoder::decode( + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid_standard = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::SET_TOKEN_STANDARD_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR], &[(false, true), (false, false), (false, false)], false, "set_token_standard_invalid", ), ); - assert_eq!(invalid_standard.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid_standard.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn collection_size_variants_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let direct = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let direct = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - set_collection_size_wire(crate::decoder::metadata::metaplex_token_metadata::SET_COLLECTION_SIZE_DISCRIMINATOR, u64::MAX) - .as_slice(), + set_collection_size_wire( + crate::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR, + u64::MAX, + ) + .as_slice(), &[(false, true), (true, true), (false, false), (false, false)], false, "set_collection_size", ), ); - assert_eq!(direct.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(direct.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(direct.observations[0].payload_json["parameters"]["size"], u64::MAX); assert_eq!( direct.observations[0].payload_json["accounts"][3]["role"], "collection_authority_record" ); - let bubblegum = crate::InstructionDecoder::decode( + let bubblegum = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - set_collection_size_wire(crate::decoder::metadata::metaplex_token_metadata::BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR, 42) - .as_slice(), + set_collection_size_wire( + crate::DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR, + 42, + ) + .as_slice(), &[(false, true), (true, false), (false, false), (true, false), (false, false)], true, "bubblegum_set_collection_size/0", ), ); - assert_eq!(bubblegum.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(bubblegum.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(bubblegum.observations[0].payload_json["parameters"]["size"], 42); assert_eq!( bubblegum.observations[0].payload_json["accounts"][3]["role"], @@ -2213,35 +2167,35 @@ mod tests { #[test] fn collection_size_variants_reject_truncated_wire_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::SET_COLLECTION_SIZE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR], &[(false, true), (true, true), (false, false)], false, "set_collection_size_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - set_collection_size_wire(crate::decoder::metadata::metaplex_token_metadata::BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR, 1) - .as_slice(), + set_collection_size_wire( + crate::DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR, + 1, + ) + .as_slice(), &[(false, true), (true, true), (false, false), (true, false)], false, "bubblegum_set_collection_size_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let mut suffix_wire = set_collection_size_wire( - crate::decoder::metadata::metaplex_token_metadata::SET_COLLECTION_SIZE_DISCRIMINATOR, - 2, - ); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let mut suffix_wire = + set_collection_size_wire(crate::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR, 2); suffix_wire.push(0); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( suffix_wire.as_slice(), @@ -2250,13 +2204,12 @@ mod tests { "set_collection_size_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn programmable_delegate_and_revoke_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = &[ (false, true), (false, false), @@ -2273,7 +2226,7 @@ mod tests { (false, false), (false, false), ]; - let delegate = crate::InstructionDecoder::decode( + let delegate = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( delegate_wire(&mpl_token_metadata::types::DelegateArgs::StandardV1 { @@ -2285,7 +2238,7 @@ mod tests { "delegate", ), ); - assert_eq!(delegate.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(delegate.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( delegate.observations[0].payload_json["parameters"]["StandardV1"]["amount"], u64::MAX @@ -2294,7 +2247,7 @@ mod tests { delegate.observations[0].payload_json["accounts"][10]["role"], "sysvar_instructions" ); - let revoke = crate::InstructionDecoder::decode( + let revoke = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( revoke_wire(&mpl_token_metadata::types::RevokeArgs::StandardV1).as_slice(), @@ -2303,15 +2256,14 @@ mod tests { "revoke/0", ), ); - assert_eq!(revoke.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(revoke.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!revoke.observations[0].observation_committed); assert_eq!(revoke.observations[0].payload_json["parameters"], "StandardV1"); } #[test] fn programmable_delegate_and_revoke_reject_truncated_invalid_and_suffix_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = &[ (false, false), (false, false), @@ -2328,19 +2280,19 @@ mod tests { (false, false), (false, false), ]; - let truncated = crate::InstructionDecoder::decode( + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::DELEGATE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DELEGATE_DISCRIMINATOR], flags, false, "delegate_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut invalid_flags = flags.to_vec(); invalid_flags[7] = (false, false); - let invalid = crate::InstructionDecoder::decode( + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( revoke_wire(&mpl_token_metadata::types::RevokeArgs::TransferV1).as_slice(), @@ -2349,23 +2301,22 @@ mod tests { "revoke_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut suffix_wire = delegate_wire(&mpl_token_metadata::types::DelegateArgs::CollectionV1 { authorization_data: std::option::Option::None, }); suffix_wire.push(0); - let suffix = crate::InstructionDecoder::decode( + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(suffix_wire.as_slice(), flags, false, "delegate_suffix"), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn programmable_lifecycle_transfer_lock_unlock_burn_and_close_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let transfer_flags = &[ (false, true), (false, false), @@ -2385,11 +2336,11 @@ mod tests { (false, false), (false, false), ]; - let transfer = crate::InstructionDecoder::decode( + let transfer = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::TRANSFER_DISCRIMINATOR, + crate::DC_METADATA_MTM_TRANSFER_DISCRIMINATOR, &mpl_token_metadata::types::TransferArgs::V1 { amount: u64::MAX, authorization_data: std::option::Option::None, @@ -2401,7 +2352,7 @@ mod tests { "transfer", ), ); - assert_eq!(transfer.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(transfer.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(transfer.observations[0].payload_json["parameters"]["V1"]["amount"], u64::MAX); assert_eq!( transfer.observations[0].payload_json["accounts"][8]["role"], @@ -2422,11 +2373,11 @@ mod tests { (false, false), (false, false), ]; - let lock = crate::InstructionDecoder::decode( + let lock = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::LOCK_DISCRIMINATOR, + crate::DC_METADATA_MTM_LOCK_DISCRIMINATOR, &mpl_token_metadata::types::LockArgs::V1 { authorization_data: std::option::Option::None, }, @@ -2437,12 +2388,12 @@ mod tests { "lock", ), ); - assert_eq!(lock.status, crate::DecoderOutcomeStatus::Decoded); - let unlock = crate::InstructionDecoder::decode( + assert_eq!(lock.status, crate::DcApiDecoderOutcomeStatus::Decoded); + let unlock = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::UNLOCK_DISCRIMINATOR, + crate::DC_METADATA_MTM_UNLOCK_DISCRIMINATOR, &mpl_token_metadata::types::UnlockArgs::V1 { authorization_data: std::option::Option::None, }, @@ -2453,7 +2404,7 @@ mod tests { "unlock/0", ), ); - assert_eq!(unlock.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(unlock.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!unlock.observations[0].observation_committed); let burn_flags = &[ (true, true), @@ -2471,11 +2422,11 @@ mod tests { (false, false), (false, false), ]; - let burn = crate::InstructionDecoder::decode( + let burn = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::BURN_DISCRIMINATOR, + crate::DC_METADATA_MTM_BURN_DISCRIMINATOR, &mpl_token_metadata::types::BurnArgs::V1 { amount: u64::MAX }, ) .as_slice(), @@ -2484,40 +2435,39 @@ mod tests { "burn", ), ); - assert_eq!(burn.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(burn.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(burn.observations[0].payload_json["parameters"]["V1"]["amount"], u64::MAX); - let close = crate::InstructionDecoder::decode( + let close = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CLOSE_ACCOUNTS_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR], &[(false, true), (false, true), (false, true), (true, false), (false, true)], false, "close_accounts", ), ); - assert_eq!(close.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(close.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(close.observations[0].payload_json["accounts"][4]["role"], "destination"); } #[test] fn programmable_lifecycle_rejects_truncated_invalid_and_suffix_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::TRANSFER_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_TRANSFER_DISCRIMINATOR], &[(false, true); 17], false, "transfer_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( programmable_wire( - crate::decoder::metadata::metaplex_token_metadata::BURN_DISCRIMINATOR, + crate::DC_METADATA_MTM_BURN_DISCRIMINATOR, &mpl_token_metadata::types::BurnArgs::V1 { amount: 1 }, ) .as_slice(), @@ -2541,86 +2491,80 @@ mod tests { "burn_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[ - crate::decoder::metadata::metaplex_token_metadata::CLOSE_ACCOUNTS_DISCRIMINATOR, - 0, - ], + &[crate::DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR, 0], &[(false, true), (false, true), (false, true), (true, false), (false, true)], false, "close_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn legacy_delegated_freeze_and_thaw_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; let flags = &[(true, true), (false, true), (false, false), (false, false), (false, false)]; - let freeze = crate::InstructionDecoder::decode( + let freeze = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR], flags, false, "freeze_delegated_account", ), ); - assert_eq!(freeze.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(freeze.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(freeze.observations[0].payload_json["accounts"][0]["role"], "delegate"); assert_eq!(freeze.observations[0].payload_json["accounts"][4]["role"], "token_program"); - let thaw = crate::InstructionDecoder::decode( + let thaw = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::THAW_DELEGATED_ACCOUNT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR], flags, true, "thaw_delegated_account/0", ), ); - assert_eq!(thaw.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(thaw.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!thaw.observations[0].observation_committed); } #[test] fn legacy_delegated_freeze_and_thaw_reject_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR], &[(false, true), (false, true), (false, false), (false, false), (false, false)], false, "freeze_delegated_account_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::THAW_DELEGATED_ACCOUNT_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR, 0], &[(true, true), (false, true), (false, false), (false, false), (false, false)], false, "thaw_delegated_account_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn legacy_nft_burn_and_printing_token_mint_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let burn_nft = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let burn_nft = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::BURN_NFT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR], &[ (false, true), (true, true), @@ -2634,15 +2578,15 @@ mod tests { "burn_nft", ), ); - assert_eq!(burn_nft.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(burn_nft.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( burn_nft.observations[0].payload_json["accounts"][6]["role"], "collection_metadata" ); - let burn_edition = crate::InstructionDecoder::decode( + let burn_edition = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::BURN_EDITION_NFT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR], &[ (false, true), (true, true), @@ -2659,16 +2603,16 @@ mod tests { "burn_edition_nft/0", ), ); - assert_eq!(burn_edition.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(burn_edition.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!burn_edition.observations[0].observation_committed); assert_eq!( burn_edition.observations[0].payload_json["accounts"][8]["role"], "edition_marker_account" ); - let printing = crate::InstructionDecoder::decode( + let printing = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2691,7 +2635,7 @@ mod tests { "deprecated_printing_token", ), ); - assert_eq!(printing.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(printing.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( printing.observations[0].payload_json["accounts"][15]["role"], "reservation_list" @@ -2700,12 +2644,11 @@ mod tests { #[test] fn legacy_nft_burn_and_printing_token_mint_reject_invalid_flags_and_suffixes() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::BURN_NFT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2718,11 +2661,11 @@ mod tests { "burn_nft_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::BURN_EDITION_NFT_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR, 0], &[ (false, true), (true, true), @@ -2739,27 +2682,26 @@ mod tests { "burn_edition_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); - let truncated_accounts = crate::InstructionDecoder::decode( + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); + let truncated_accounts = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR], &[(false, true); 14], false, "deprecated_printing_token_truncated", ), ); - assert_eq!(truncated_accounts.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated_accounts.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn escrow_and_collect_family_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let create = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let create = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CREATE_ESCROW_ACCOUNT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2775,12 +2717,12 @@ mod tests { "create_escrow_account", ), ); - assert_eq!(create.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(create.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(create.observations[0].payload_json["accounts"][8]["role"], "authority"); - let close = crate::InstructionDecoder::decode( + let close = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2795,13 +2737,11 @@ mod tests { "close_escrow_account/0", ), ); - assert_eq!(close.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(close.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!close.observations[0].observation_committed); - let mut transfer_wire = vec![ - crate::decoder::metadata::metaplex_token_metadata::TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR, - ]; + let mut transfer_wire = vec![crate::DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR]; transfer_wire.extend_from_slice(&u64::MAX.to_le_bytes()); - let transfer = crate::InstructionDecoder::decode( + let transfer = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( transfer_wire.as_slice(), @@ -2824,30 +2764,29 @@ mod tests { "transfer_out_of_escrow", ), ); - assert_eq!(transfer.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(transfer.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(transfer.observations[0].payload_json["parameters"]["amount"], u64::MAX); assert_eq!(transfer.observations[0].payload_json["accounts"][12]["role"], "authority"); - let collect = crate::InstructionDecoder::decode( + let collect = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::COLLECT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_COLLECT_DISCRIMINATOR], &[(true, false), (false, false)], false, "collect", ), ); - assert_eq!(collect.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(collect.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(collect.observations[0].payload_json["accounts"][1]["role"], "recipient"); } #[test] fn escrow_and_collect_family_reject_truncated_invalid_and_suffix_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let truncated = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let truncated = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR], &[ (false, false), (false, true), @@ -2866,11 +2805,11 @@ mod tests { "transfer_out_of_escrow_truncated", ), ); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let invalid = crate::InstructionDecoder::decode( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CREATE_ESCROW_ACCOUNT_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2885,27 +2824,26 @@ mod tests { "create_escrow_account_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::COLLECT_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_COLLECT_DISCRIMINATOR, 0], &[(true, false), (false, false)], false, "collect_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn resize_and_migrate_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let resize = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let resize = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::RESIZE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_RESIZE_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2919,12 +2857,12 @@ mod tests { "resize", ), ); - assert_eq!(resize.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(resize.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(resize.observations[0].payload_json["accounts"][4]["role"], "authority"); - let migrate = crate::InstructionDecoder::decode( + let migrate = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::MIGRATE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_MIGRATE_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2946,19 +2884,18 @@ mod tests { "migrate/0", ), ); - assert_eq!(migrate.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(migrate.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!migrate.observations[0].observation_committed); assert_eq!(migrate.observations[0].payload_json["accounts"][9]["role"], "token_record"); } #[test] fn resize_and_migrate_reject_invalid_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid_resize = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid_resize = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::RESIZE_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_RESIZE_DISCRIMINATOR], &[ (false, true), (false, true), @@ -2972,11 +2909,11 @@ mod tests { "resize_invalid", ), ); - assert_eq!(invalid_resize.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid_resize.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::MIGRATE_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_MIGRATE_DISCRIMINATOR, 0], &[ (false, true), (false, true), @@ -2998,17 +2935,16 @@ mod tests { "migrate_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn omitted_historical_discriminators_decode_exact_contracts() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; type HistoricalCase<'a> = (&'a [u8], &'a [(bool, bool)], &'a str, usize, &'a str); let cases: &[HistoricalCase<'_>] = &[ ( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR], &[ (false, true), (false, true), @@ -3029,14 +2965,14 @@ mod tests { "one_time_printing_authorization_mint_authority", ), ( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR], &[(false, true), (false, true), (true, false)], "deprecated_set_reservation_list", 2, "resource", ), ( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR], &[ (false, true), (true, false), @@ -3052,7 +2988,7 @@ mod tests { "resource", ), ( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR], &[ (false, true), (false, true), @@ -3069,7 +3005,7 @@ mod tests { "burn_authority", ), ( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR], &[ (false, true), (false, true), @@ -3084,7 +3020,7 @@ mod tests { "update_authority", ), ( - &[crate::decoder::metadata::metaplex_token_metadata::CREATE_MASTER_EDITION_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR], &[ (false, true), (false, true), @@ -3102,11 +3038,11 @@ mod tests { ), ]; for (wire, flags, path, role_index, role) in cases { - let decoded = crate::InstructionDecoder::decode( + let decoded = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags(wire, flags, false, path), ); - assert_eq!(decoded.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(decoded.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( decoded.observations[0].payload_json["accounts"][*role_index]["role"], *role @@ -3116,22 +3052,21 @@ mod tests { #[test] fn omitted_historical_discriminators_reject_invalid_wires() { - let decoder = - crate::decoder::metadata::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder; - let invalid = crate::InstructionDecoder::decode( + let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder; + let invalid = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR], + &[crate::DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR], &[(false, true), (false, true), (false, false)], false, "deprecated_set_reservation_list_invalid", ), ); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); - let suffix = crate::InstructionDecoder::decode( + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); + let suffix = crate::DcApiInstructionDecoder::decode( &decoder, &input_with_flags( - &[crate::decoder::metadata::metaplex_token_metadata::CREATE_MASTER_EDITION_DISCRIMINATOR, 0], + &[crate::DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR, 0], &[ (false, true), (false, true), @@ -3147,6 +3082,6 @@ mod tests { "create_master_edition_suffix", ), ); - assert_eq!(suffix.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(suffix.status, crate::DcApiDecoderOutcomeStatus::Failed); } } diff --git a/kb-lib/src/decoder/metadata/metaplex_token_metadata/instruction.rs b/kb-lib/src/decoder/metadata/metaplex_token_metadata/instruction.rs index 0815ff1..6c83882 100644 --- a/kb-lib/src/decoder/metadata/metaplex_token_metadata/instruction.rs +++ b/kb-lib/src/decoder/metadata/metaplex_token_metadata/instruction.rs @@ -6,7 +6,7 @@ use base64::Engine; // rust-rules: trait-import use sha2::Digest; // rust-rules: trait-import -pub(crate) struct ParsedInstruction { +struct ParsedInstruction { pub(crate) code: &'static str, pub(crate) discriminator: u8, pub(crate) parameters: serde_json::Value, @@ -23,22 +23,24 @@ struct ResolvedAccount { source: serde_json::Value, } -pub(crate) fn entry_for_discriminator( +pub(crate) fn decoder_metadata_metaplex_token_metadata_entry_for_discriminator( discriminator: u8, ) -> std::option::Option<(u8, &'static str, bool)> { - return crate::decoder::metadata::metaplex_token_metadata::INSTRUCTION_ENTRIES + return crate::DC_METADATA_MTM_INSTRUCTION_ENTRIES .iter() .copied() .find(|(candidate, _, _)| return *candidate == discriminator); } -pub(crate) fn payload_discriminator( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_metadata_metaplex_token_metadata_payload_discriminator( + input: &crate::MdCoreInstructionReplayInput, ) -> std::option::Option { return decode_payload(input).ok().and_then(|value| return value.first().copied()); } -pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { +pub(crate) fn decoder_metadata_metaplex_token_metadata_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { let bytes = match decode_payload(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { @@ -59,16 +61,16 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode ); }, }; - let entry = match crate::decoder::metadata::metaplex_token_metadata::entry_for_discriminator( + let entry = match crate::decoder_metadata_metaplex_token_metadata_entry_for_discriminator( discriminator, ) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Unsupported, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Unsupported, recognized_entry_code: std::option::Option::None, observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: "unknown_metaplex_token_metadata_discriminator".to_string(), message: format!( "unknown Metaplex Token Metadata discriminator {discriminator}; payloadPrefixHex={}", @@ -121,15 +123,17 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode project_accounts(parsed.code, accounts.as_slice()), bytes.as_slice(), ); - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some(parsed.code.to_string()), observations: std::vec![observation], diagnostics: std::vec::Vec::new(), }; } -fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result> { +fn decode_payload( + input: &crate::MdCoreInstructionReplayInput, +) -> kb_core::Result> { let payload = match input.instruction_payload_json.as_ref() { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -146,10 +150,10 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< )); }, }; - if encoded.len() > crate::decoder::metadata::metaplex_token_metadata::MAX_BASE64_BYTES { + if encoded.len() > crate::DC_METADATA_MTM_MAX_BASE64_BYTES { return std::result::Result::Err(kb_core::Error::invalid_state(format!( "Metaplex Token Metadata base64 payload exceeds {} bytes", - crate::decoder::metadata::metaplex_token_metadata::MAX_BASE64_BYTES + crate::DC_METADATA_MTM_MAX_BASE64_BYTES ))); } let decoded = match base64::engine::general_purpose::STANDARD.decode(encoded.as_bytes()) { @@ -160,21 +164,16 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< ))); }, }; - if decoded.len() > crate::decoder::metadata::metaplex_token_metadata::MAX_INSTRUCTION_BYTES { + if decoded.len() > crate::DC_METADATA_MTM_MAX_INSTRUCTION_BYTES { return std::result::Result::Err(kb_core::Error::invalid_state(format!( "Metaplex Token Metadata payload exceeds {} decoded bytes", - crate::decoder::metadata::metaplex_token_metadata::MAX_INSTRUCTION_BYTES + crate::DC_METADATA_MTM_MAX_INSTRUCTION_BYTES ))); } return std::result::Result::Ok(decoded); } -fn parse_instruction( - bytes: &[u8], -) -> std::result::Result< - crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction, - std::string::String, -> { +fn parse_instruction(bytes: &[u8]) -> std::result::Result { let discriminator = match bytes.first().copied() { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -182,92 +181,92 @@ fn parse_instruction( }, }; return match discriminator { - crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + crate::DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "deprecated_create_master_edition", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "deprecated_set_reservation_list", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "deprecated_create_reservation_list", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "deprecated_mint_printing_tokens_via_token", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "deprecated_mint_printing_tokens", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::CREATE_MASTER_EDITION_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "create_master_edition", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "deprecated_mint_new_edition_from_master_edition_via_printing_token", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR - | crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR + | crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(format!("MintNewEditionFromMasterEdition edition Borsh decode failed: {error}")), }; let code = if discriminator - == crate::decoder::metadata::metaplex_token_metadata::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR + == crate::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR { "mint_new_edition_from_master_edition_via_token" } else { "mint_new_edition_from_master_edition_via_vault_proxy" }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code, discriminator, parameters: serde_json::json!({"edition": args.edition}), consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "convert_master_edition_v1_to_v2", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::CREATE_MASTER_EDITION_V3_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let max_supply = match as borsh_0_10::BorshDeserialize>::deserialize( @@ -280,50 +279,50 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "create_master_edition_v3", discriminator, parameters: serde_json::json!({"max_supply": max_supply}), consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "update_primary_sale_happened_via_token", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::SIGN_METADATA_DISCRIMINATOR => std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR => std::result::Result::Ok(ParsedInstruction { code: "sign_metadata", discriminator, parameters: serde_json::json!({}), consumed: 1, }), - crate::decoder::metadata::metaplex_token_metadata::PUFF_METADATA_DISCRIMINATOR => std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + crate::DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR => std::result::Result::Ok(ParsedInstruction { code: "puff_metadata", discriminator, parameters: serde_json::json!({}), consumed: 1, }), - crate::decoder::metadata::metaplex_token_metadata::REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + crate::DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "remove_creator_verification", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::SET_TOKEN_STANDARD_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "set_token_standard", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let data = match ::deserialize( @@ -357,14 +356,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "create_metadata_account", discriminator, parameters: serde_json::json!({"data": data_json, "is_mutable": is_mutable}), consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::UPDATE_METADATA_ACCOUNT_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let data = match as borsh_0_10::BorshDeserialize>::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -407,14 +406,14 @@ fn parse_instruction( }, }; let authority_json = new_update_authority.map(|value| return hex_bytes(&value)); - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "update_metadata_account", discriminator, parameters: serde_json::json!({"data": data_json, "new_update_authority_hex": authority_json, "primary_sale_happened": primary_sale_happened}), consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let data = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -441,7 +440,7 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "create_metadata_account_v2", discriminator, parameters: serde_json::json!({ @@ -450,8 +449,8 @@ fn parse_instruction( }), consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -469,14 +468,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "create_metadata_account_v3", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::TRANSFER_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_TRANSFER_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -490,14 +489,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "transfer", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::LOCK_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_LOCK_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -511,14 +510,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "lock", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::UNLOCK_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_UNLOCK_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -532,30 +531,30 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "unlock", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::CREATE_ESCROW_ACCOUNT_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "create_escrow_account", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "close_escrow_account", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let amount = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -565,34 +564,34 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "transfer_out_of_escrow", discriminator, parameters: serde_json::json!({"amount": amount}), consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::COLLECT_DISCRIMINATOR => std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_COLLECT_DISCRIMINATOR => std::result::Result::Ok(ParsedInstruction { code: "collect", discriminator, parameters: serde_json::json!({}), consumed: 1, }), - crate::decoder::metadata::metaplex_token_metadata::BURN_NFT_DISCRIMINATOR => std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + crate::DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR => std::result::Result::Ok(ParsedInstruction { code: "burn_nft", discriminator, parameters: serde_json::json!({}), consumed: 1, }), - crate::decoder::metadata::metaplex_token_metadata::BURN_EDITION_NFT_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + crate::DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "burn_edition_nft", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::CREATE_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_CREATE_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -606,14 +605,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "create", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::MINT_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_MINT_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -627,14 +626,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "mint", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::PRINT_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_PRINT_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -648,26 +647,26 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "print", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::MIGRATE_DISCRIMINATOR => std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_MIGRATE_DISCRIMINATOR => std::result::Result::Ok(ParsedInstruction { code: "migrate", discriminator, parameters: serde_json::json!({}), consumed: 1, }), - crate::decoder::metadata::metaplex_token_metadata::RESIZE_DISCRIMINATOR => std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + crate::DC_METADATA_MTM_RESIZE_DISCRIMINATOR => std::result::Result::Ok(ParsedInstruction { code: "resize", discriminator, parameters: serde_json::json!({}), consumed: 1, }), - crate::decoder::metadata::metaplex_token_metadata::USE_DISCRIMINATOR => { + crate::DC_METADATA_MTM_USE_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -681,14 +680,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "use", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::VERIFY_DISCRIMINATOR | crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_VERIFY_DISCRIMINATOR | crate::DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -703,15 +702,15 @@ fn parse_instruction( }, }; let code = - if discriminator == crate::decoder::metadata::metaplex_token_metadata::VERIFY_DISCRIMINATOR { "verify" } else { "unverify" }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + if discriminator == crate::DC_METADATA_MTM_VERIFY_DISCRIMINATOR { "verify" } else { "unverify" }; + std::result::Result::Ok(ParsedInstruction { code, discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::UPDATE_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_UPDATE_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -725,14 +724,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "update", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::BURN_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_BURN_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -746,20 +745,20 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "burn", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::CLOSE_ACCOUNTS_DISCRIMINATOR => std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR => std::result::Result::Ok(ParsedInstruction { code: "close_accounts", discriminator, parameters: serde_json::json!({}), consumed: 1, }), - crate::decoder::metadata::metaplex_token_metadata::DELEGATE_DISCRIMINATOR => { + crate::DC_METADATA_MTM_DELEGATE_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -773,14 +772,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "delegate", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::REVOKE_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_REVOKE_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -794,97 +793,97 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "revoke", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::SET_COLLECTION_SIZE_DISCRIMINATOR - | crate::decoder::metadata::metaplex_token_metadata::BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR + | crate::DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(format!("SetCollectionSize Borsh decode failed: {error}")), }; - let code = if discriminator == crate::decoder::metadata::metaplex_token_metadata::SET_COLLECTION_SIZE_DISCRIMINATOR { + let code = if discriminator == crate::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR { "set_collection_size" } else { "bubblegum_set_collection_size" }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code, discriminator, parameters: serde_json::json!({"size": args.size}), consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::VERIFY_COLLECTION_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "verify_collection", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_COLLECTION_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "unverify_collection", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::SET_AND_VERIFY_COLLECTION_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "set_and_verify_collection", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "approve_collection_authority", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "revoke_collection_authority", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "verify_sized_collection_item", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "unverify_sized_collection_item", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "set_and_verify_sized_collection_item", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::UTILIZE_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_UTILIZE_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -898,14 +897,14 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "utilize", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::APPROVE_USE_AUTHORITY_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -919,38 +918,38 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "approve_use_authority", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, - crate::decoder::metadata::metaplex_token_metadata::REVOKE_USE_AUTHORITY_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "revoke_use_authority", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "freeze_delegated_account", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::THAW_DELEGATED_ACCOUNT_DISCRIMINATOR => { - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + } + crate::DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR => { + std::result::Result::Ok(ParsedInstruction { code: "thaw_delegated_account", discriminator, parameters: serde_json::json!({}), consumed: 1, }) - }, - crate::decoder::metadata::metaplex_token_metadata::UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR => { + } + crate::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR => { let mut remaining = &bytes[1..]; let args = match ::deserialize(&mut remaining) { std::result::Result::Ok(value) => value, @@ -970,13 +969,13 @@ fn parse_instruction( )); }, }; - std::result::Result::Ok(crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction { + std::result::Result::Ok(ParsedInstruction { code: "update_metadata_account_v2", discriminator, parameters, consumed: bytes.len().saturating_sub(remaining.len()), }) - }, + } _ => std::result::Result::Err(format!("unsupported discriminator {discriminator}")), }; } @@ -1032,7 +1031,7 @@ fn validate_data_v2( } fn resolve_accounts( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result> { let instruction_accounts = match input.instruction_accounts_json.as_array() { std::option::Option::Some(value) => value, @@ -1042,9 +1041,7 @@ fn resolve_accounts( )); }, }; - if instruction_accounts.len() - > crate::decoder::metadata::metaplex_token_metadata::MAX_INSTRUCTION_ACCOUNTS - { + if instruction_accounts.len() > crate::DC_METADATA_MTM_MAX_INSTRUCTION_ACCOUNTS { return std::result::Result::Err(kb_core::Error::invalid_state( "Metaplex Token Metadata instruction account count exceeds bound", )); @@ -2642,43 +2639,39 @@ fn project_accounts(code: &str, accounts: &[ResolvedAccount]) -> serde_json::Val } fn observation( - input: &crate::CoreInstructionReplayInput, - parsed: &crate::decoder::metadata::metaplex_token_metadata::ParsedInstruction, + input: &crate::MdCoreInstructionReplayInput, + parsed: &ParsedInstruction, accounts: serde_json::Value, wire: &[u8], -) -> crate::DecodedObservation { +) -> crate::DcApiDecodedObservation { let wire_hash = hash(wire); let committed = !input.transaction_failed; - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(input.instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode( - crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE.to_string(), - ), - surface_code: crate::SurfaceCode( - crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE.to_string(), - ), - event_code: crate::EventCode(format!( + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(input.instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode(crate::DC_METADATA_MTM_SURFACE_CODE.to_string()), + surface_code: crate::MdSurfaceCode(crate::DC_METADATA_MTM_SURFACE_CODE.to_string()), + event_code: crate::MdEventCode(format!( "{}.{}", - crate::decoder::metadata::metaplex_token_metadata::SURFACE_CODE, + crate::DC_METADATA_MTM_SURFACE_CODE, parsed.code )), - event_name: crate::EventName(parsed.code.to_string()), - event_family: crate::EventFamily::Metadata, + event_name: crate::MdEventName(parsed.code.to_string()), + event_family: crate::MdEventFamily::Metadata, source_kind: if input.instruction_path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction }, - confidence: crate::DecoderConfidence::ManualExact, + confidence: crate::MdDecoderConfidence::ManualExact, }; - return crate::DecodedObservation { + return crate::DcApiDecodedObservation { event_key: format!("metaplex_token_metadata:{}:0", parsed.code), event, payload_json: serde_json::json!({ - "eventVersion": crate::decoder::metadata::metaplex_token_metadata::EVENT_VERSION, + "eventVersion": crate::DC_METADATA_MTM_EVENT_VERSION, "programId": input.program_id, "instruction": parsed.code, "wireDiscriminator": parsed.discriminator, @@ -2695,9 +2688,9 @@ fn observation( transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: committed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec![ "mpl_token_metadata_5_1_1_generated_wire".to_string(), format!("wire_discriminator:{}", parsed.discriminator), @@ -2717,10 +2710,7 @@ fn hash(bytes: &[u8]) -> std::string::String { } fn hex_prefix(bytes: &[u8]) -> std::string::String { - let length = std::cmp::min( - bytes.len(), - crate::decoder::metadata::metaplex_token_metadata::DIAGNOSTIC_PREFIX_BYTES, - ); + let length = std::cmp::min(bytes.len(), crate::DC_METADATA_MTM_DIAGNOSTIC_PREFIX_BYTES); let mut output = std::string::String::with_capacity(length.saturating_mul(2)); for byte in &bytes[..length] { output.push_str(format!("{byte:02x}").as_str()); @@ -2732,12 +2722,12 @@ fn failed( entry_code: std::option::Option<&str>, code: &str, message: std::string::String, -) -> crate::DecoderExecutionResult { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, +) -> crate::DcApiDecoderExecutionResult { + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: entry_code.map(str::to_string), observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: code.to_string(), message, retriable: false diff --git a/kb-lib/src/decoder/metadata/spl_name_service.rs b/kb-lib/src/decoder/metadata/spl_name_service.rs index 108c6e9..11dce57 100644 --- a/kb-lib/src/decoder/metadata/spl_name_service.rs +++ b/kb-lib/src/decoder/metadata/spl_name_service.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_metadata_spl_name_service`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_metadata_spl_name_service"; +const LEGACY_CRATE: &str = "kb_decoder_metadata_spl_name_service"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/nft.rs b/kb-lib/src/decoder/nft.rs index bdf5c67..96c59e8 100644 --- a/kb-lib/src/decoder/nft.rs +++ b/kb-lib/src/decoder/nft.rs @@ -3,4 +3,4 @@ //! `nft` decoder family. -pub mod metaplex_bubblegum; +mod metaplex_bubblegum; diff --git a/kb-lib/src/decoder/nft/metaplex_bubblegum.rs b/kb-lib/src/decoder/nft/metaplex_bubblegum.rs index 18fc116..182571b 100644 --- a/kb-lib/src/decoder/nft/metaplex_bubblegum.rs +++ b/kb-lib/src/decoder/nft/metaplex_bubblegum.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_nft_metaplex_bubblegum`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_nft_metaplex_bubblegum"; +const LEGACY_CRATE: &str = "kb_decoder_nft_metaplex_bubblegum"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/orderbook.rs b/kb-lib/src/decoder/orderbook.rs index fd86e45..c9204aa 100644 --- a/kb-lib/src/decoder/orderbook.rs +++ b/kb-lib/src/decoder/orderbook.rs @@ -3,6 +3,6 @@ //! `orderbook` decoder family. -pub mod jupiter_limit_order; -pub mod jupiter_limit_order_v2; -pub mod openbook_v2; +mod jupiter_limit_order; +mod jupiter_limit_order_v2; +mod openbook_v2; diff --git a/kb-lib/src/decoder/orderbook/jupiter_limit_order.rs b/kb-lib/src/decoder/orderbook/jupiter_limit_order.rs index 8d5c111..18ebf24 100644 --- a/kb-lib/src/decoder/orderbook/jupiter_limit_order.rs +++ b/kb-lib/src/decoder/orderbook/jupiter_limit_order.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_orderbook_jupiter_limit_order`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_orderbook_jupiter_limit_order"; +const LEGACY_CRATE: &str = "kb_decoder_orderbook_jupiter_limit_order"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/orderbook/jupiter_limit_order_v2.rs b/kb-lib/src/decoder/orderbook/jupiter_limit_order_v2.rs index 148be1d..4d9ebd7 100644 --- a/kb-lib/src/decoder/orderbook/jupiter_limit_order_v2.rs +++ b/kb-lib/src/decoder/orderbook/jupiter_limit_order_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_orderbook_jupiter_limit_order_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_orderbook_jupiter_limit_order_v2"; +const LEGACY_CRATE: &str = "kb_decoder_orderbook_jupiter_limit_order_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/orderbook/openbook_v2.rs b/kb-lib/src/decoder/orderbook/openbook_v2.rs index a01b635..5a40204 100644 --- a/kb-lib/src/decoder/orderbook/openbook_v2.rs +++ b/kb-lib/src/decoder/orderbook/openbook_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_orderbook_openbook_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_orderbook_openbook_v2"; +const LEGACY_CRATE: &str = "kb_decoder_orderbook_openbook_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/perpetuals.rs b/kb-lib/src/decoder/perpetuals.rs index 7e2f027..d60238b 100644 --- a/kb-lib/src/decoder/perpetuals.rs +++ b/kb-lib/src/decoder/perpetuals.rs @@ -3,6 +3,6 @@ //! `perpetuals` decoder family. -pub mod drift_v2; -pub mod jupiter; -pub mod zeta; +mod drift_v2; +mod jupiter; +mod zeta; diff --git a/kb-lib/src/decoder/perpetuals/drift_v2.rs b/kb-lib/src/decoder/perpetuals/drift_v2.rs index f0c503a..7cf6f36 100644 --- a/kb-lib/src/decoder/perpetuals/drift_v2.rs +++ b/kb-lib/src/decoder/perpetuals/drift_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_perpetuals_drift_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_perpetuals_drift_v2"; +const LEGACY_CRATE: &str = "kb_decoder_perpetuals_drift_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/perpetuals/jupiter.rs b/kb-lib/src/decoder/perpetuals/jupiter.rs index 3fd691c..6900b7e 100644 --- a/kb-lib/src/decoder/perpetuals/jupiter.rs +++ b/kb-lib/src/decoder/perpetuals/jupiter.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_perpetuals_jupiter`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_perpetuals_jupiter"; +const LEGACY_CRATE: &str = "kb_decoder_perpetuals_jupiter"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/perpetuals/zeta.rs b/kb-lib/src/decoder/perpetuals/zeta.rs index 04db283..9ed6d85 100644 --- a/kb-lib/src/decoder/perpetuals/zeta.rs +++ b/kb-lib/src/decoder/perpetuals/zeta.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_perpetuals_zeta`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_perpetuals_zeta"; +const LEGACY_CRATE: &str = "kb_decoder_perpetuals_zeta"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/router.rs b/kb-lib/src/decoder/router.rs index da9fb10..db89189 100644 --- a/kb-lib/src/decoder/router.rs +++ b/kb-lib/src/decoder/router.rs @@ -3,9 +3,9 @@ //! `router` decoder family. -pub mod dflow_aggregator_v4; -pub mod jupiter_aggregator_v4; -pub mod jupiter_aggregator_v6; -pub mod jupiter_dca; -pub mod okx_labs_v1; -pub mod okx_labs_v2; +mod dflow_aggregator_v4; +mod jupiter_aggregator_v4; +mod jupiter_aggregator_v6; +mod jupiter_dca; +mod okx_labs_v1; +mod okx_labs_v2; diff --git a/kb-lib/src/decoder/router/dflow_aggregator_v4.rs b/kb-lib/src/decoder/router/dflow_aggregator_v4.rs index 7150dc0..ea335f5 100644 --- a/kb-lib/src/decoder/router/dflow_aggregator_v4.rs +++ b/kb-lib/src/decoder/router/dflow_aggregator_v4.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_router_dflow_aggregator_v4`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_router_dflow_aggregator_v4"; +const LEGACY_CRATE: &str = "kb_decoder_router_dflow_aggregator_v4"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/router/jupiter_aggregator_v4.rs b/kb-lib/src/decoder/router/jupiter_aggregator_v4.rs index cac6b3b..15fac7c 100644 --- a/kb-lib/src/decoder/router/jupiter_aggregator_v4.rs +++ b/kb-lib/src/decoder/router/jupiter_aggregator_v4.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_router_jupiter_aggregator_v4`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_router_jupiter_aggregator_v4"; +const LEGACY_CRATE: &str = "kb_decoder_router_jupiter_aggregator_v4"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/router/jupiter_aggregator_v6.rs b/kb-lib/src/decoder/router/jupiter_aggregator_v6.rs index d59ea39..ee4d9c7 100644 --- a/kb-lib/src/decoder/router/jupiter_aggregator_v6.rs +++ b/kb-lib/src/decoder/router/jupiter_aggregator_v6.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_router_jupiter_aggregator_v6`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_router_jupiter_aggregator_v6"; +const LEGACY_CRATE: &str = "kb_decoder_router_jupiter_aggregator_v6"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/router/jupiter_dca.rs b/kb-lib/src/decoder/router/jupiter_dca.rs index 4ca27be..5c7cc29 100644 --- a/kb-lib/src/decoder/router/jupiter_dca.rs +++ b/kb-lib/src/decoder/router/jupiter_dca.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_router_jupiter_dca`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_router_jupiter_dca"; +const LEGACY_CRATE: &str = "kb_decoder_router_jupiter_dca"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/router/okx_labs_v1.rs b/kb-lib/src/decoder/router/okx_labs_v1.rs index 96e8576..0abbe74 100644 --- a/kb-lib/src/decoder/router/okx_labs_v1.rs +++ b/kb-lib/src/decoder/router/okx_labs_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_router_okx_labs_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_router_okx_labs_v1"; +const LEGACY_CRATE: &str = "kb_decoder_router_okx_labs_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/router/okx_labs_v2.rs b/kb-lib/src/decoder/router/okx_labs_v2.rs index cdd22a9..59839ea 100644 --- a/kb-lib/src/decoder/router/okx_labs_v2.rs +++ b/kb-lib/src/decoder/router/okx_labs_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_router_okx_labs_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_router_okx_labs_v2"; +const LEGACY_CRATE: &str = "kb_decoder_router_okx_labs_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/rwa.rs b/kb-lib/src/decoder/rwa.rs index 1099e82..007477d 100644 --- a/kb-lib/src/decoder/rwa.rs +++ b/kb-lib/src/decoder/rwa.rs @@ -3,4 +3,4 @@ //! `rwa` decoder family. -pub mod ondo_global_markets; +mod ondo_global_markets; diff --git a/kb-lib/src/decoder/rwa/ondo_global_markets.rs b/kb-lib/src/decoder/rwa/ondo_global_markets.rs index 68bfa69..446eb84 100644 --- a/kb-lib/src/decoder/rwa/ondo_global_markets.rs +++ b/kb-lib/src/decoder/rwa/ondo_global_markets.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_rwa_ondo_global_markets`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_rwa_ondo_global_markets"; +const LEGACY_CRATE: &str = "kb_decoder_rwa_ondo_global_markets"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/solana.rs b/kb-lib/src/decoder/solana.rs index caba2b8..3529201 100644 --- a/kb-lib/src/decoder/solana.rs +++ b/kb-lib/src/decoder/solana.rs @@ -5,91 +5,91 @@ mod core; -pub(crate) use self::core::SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_BPF_LOADER_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_CONFIG_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES; -pub(crate) use self::core::SOLANA_CORE_ED25519_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_FEATURE_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_LOADER_V4_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES; -pub(crate) use self::core::SOLANA_CORE_NATIVE_EVENT_VERSION; -pub(crate) use self::core::SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES; -pub(crate) use self::core::SOLANA_CORE_PROTOCOL_CODE; -pub(crate) use self::core::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; -pub(crate) use self::core::SOLANA_CORE_SECP256K1_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_SECP256R1_MAX_SIGNATURES; -pub(crate) use self::core::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES; -pub(crate) use self::core::SOLANA_CORE_SECP256R1_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_SIGNATURE_BYTES; -pub(crate) use self::core::SOLANA_CORE_SLASHING_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_STAKE_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_SYSTEM_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_TRACING_TARGET; -pub(crate) use self::core::SOLANA_CORE_U8_OFFSETS_BYTES; -pub(crate) use self::core::SOLANA_CORE_U16_OFFSETS_BYTES; -pub(crate) use self::core::SOLANA_CORE_VOTE_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE; -pub(crate) use self::core::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE; -pub(crate) use self::core::SolanaCoreAccountRole; -pub(crate) use self::core::SolanaCoreResolvedInstructionPayload; -pub(crate) use self::core::solana_core_address_lookup_table_coverage; -pub(crate) use self::core::solana_core_address_lookup_table_decode; -pub(crate) use self::core::solana_core_address_lookup_table_recognize; -pub(crate) use self::core::solana_core_bounded_hexadecimal_prefix; -pub(crate) use self::core::solana_core_bounded_slice; -pub(crate) use self::core::solana_core_compute_budget_coverage; -pub(crate) use self::core::solana_core_compute_budget_decode; -pub(crate) use self::core::solana_core_compute_budget_recognize; -pub(crate) use self::core::solana_core_config_coverage; -pub(crate) use self::core::solana_core_config_decode; -pub(crate) use self::core::solana_core_config_recognize; -pub(crate) use self::core::solana_core_decode_instruction_data; -pub(crate) use self::core::solana_core_decoded_payload_length; -pub(crate) use self::core::solana_core_decoded_payload_sha256; -pub(crate) use self::core::solana_core_decoded_result; -pub(crate) use self::core::solana_core_failed_result; -pub(crate) use self::core::solana_core_feature_coverage; -pub(crate) use self::core::solana_core_feature_decode; -pub(crate) use self::core::solana_core_feature_recognize; -pub(crate) use self::core::solana_core_hash_bytes; -pub(crate) use self::core::solana_core_hexadecimal_prefix; -pub(crate) use self::core::solana_core_loaders_coverage; -pub(crate) use self::core::solana_core_loaders_decode; -pub(crate) use self::core::solana_core_loaders_recognize; -pub(crate) use self::core::solana_core_payload_hash; -pub(crate) use self::core::solana_core_precompiles_coverage; -pub(crate) use self::core::solana_core_precompiles_decode; -pub(crate) use self::core::solana_core_precompiles_recognize; -pub(crate) use self::core::solana_core_read_u32_le; -pub(crate) use self::core::solana_core_read_u64_le; -pub(crate) use self::core::solana_core_resolve_accounts; -pub(crate) use self::core::solana_core_resolve_u8_instruction_payload; -pub(crate) use self::core::solana_core_resolve_u16_instruction_payload; -pub(crate) use self::core::solana_core_slashing_coverage; -pub(crate) use self::core::solana_core_slashing_decode; -pub(crate) use self::core::solana_core_slashing_recognize; -pub(crate) use self::core::solana_core_stake_coverage; -pub(crate) use self::core::solana_core_stake_decode; -pub(crate) use self::core::solana_core_stake_recognize; -pub(crate) use self::core::solana_core_system_coverage; -pub(crate) use self::core::solana_core_system_decode; -pub(crate) use self::core::solana_core_system_recognize; -pub(crate) use self::core::solana_core_target_outer_instruction_index; -pub(crate) use self::core::solana_core_unsupported_result; -pub(crate) use self::core::solana_core_vote_coverage; -pub(crate) use self::core::solana_core_vote_decode; -pub(crate) use self::core::solana_core_vote_recognize; -pub(crate) use self::core::solana_core_zk_elgamal_coverage; -pub(crate) use self::core::solana_core_zk_elgamal_decode; -pub(crate) use self::core::solana_core_zk_elgamal_recognize; -pub(crate) use self::core::solana_core_zk_token_proof_coverage; -pub(crate) use self::core::solana_core_zk_token_proof_decode; -pub(crate) use self::core::solana_core_zk_token_proof_recognize; +pub(crate) use self::core::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_BPF_LOADER_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_CONFIG_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_ED25519_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_FEATURE_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_NATIVE_EVENT_VERSION; +pub(crate) use self::core::DC_SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_PROTOCOL_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_SECP256R1_MAX_SIGNATURES; +pub(crate) use self::core::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_SECP256R1_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_SIGNATURE_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_SLASHING_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_STAKE_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_TRACING_TARGET; +pub(crate) use self::core::DC_SOLANA_CORE_U8_OFFSETS_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_U16_OFFSETS_BYTES; +pub(crate) use self::core::DC_SOLANA_CORE_VOTE_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE; +pub(crate) use self::core::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE; +pub(crate) use self::core::DcSolanaCoreAccountRole; +pub(crate) use self::core::DcSolanaCoreResolvedInstructionPayload; +pub(crate) use self::core::decoder_solana_core_address_lookup_table_coverage; +pub(crate) use self::core::decoder_solana_core_address_lookup_table_decode; +pub(crate) use self::core::decoder_solana_core_address_lookup_table_recognize; +pub(crate) use self::core::decoder_solana_core_bounded_hexadecimal_prefix; +pub(crate) use self::core::decoder_solana_core_bounded_slice; +pub(crate) use self::core::decoder_solana_core_compute_budget_coverage; +pub(crate) use self::core::decoder_solana_core_compute_budget_decode; +pub(crate) use self::core::decoder_solana_core_compute_budget_recognize; +pub(crate) use self::core::decoder_solana_core_config_coverage; +pub(crate) use self::core::decoder_solana_core_config_decode; +pub(crate) use self::core::decoder_solana_core_config_recognize; +pub(crate) use self::core::decoder_solana_core_decode_instruction_data; +pub(crate) use self::core::decoder_solana_core_decoded_payload_length; +pub(crate) use self::core::decoder_solana_core_decoded_payload_sha256; +pub(crate) use self::core::decoder_solana_core_decoded_result; +pub(crate) use self::core::decoder_solana_core_failed_result; +pub(crate) use self::core::decoder_solana_core_feature_coverage; +pub(crate) use self::core::decoder_solana_core_feature_decode; +pub(crate) use self::core::decoder_solana_core_feature_recognize; +pub(crate) use self::core::decoder_solana_core_hash_bytes; +pub(crate) use self::core::decoder_solana_core_hexadecimal_prefix; +pub(crate) use self::core::decoder_solana_core_loaders_coverage; +pub(crate) use self::core::decoder_solana_core_loaders_decode; +pub(crate) use self::core::decoder_solana_core_loaders_recognize; +pub(crate) use self::core::decoder_solana_core_payload_hash; +pub(crate) use self::core::decoder_solana_core_precompiles_coverage; +pub(crate) use self::core::decoder_solana_core_precompiles_decode; +pub(crate) use self::core::decoder_solana_core_precompiles_recognize; +pub(crate) use self::core::decoder_solana_core_read_u32_le; +pub(crate) use self::core::decoder_solana_core_read_u64_le; +pub(crate) use self::core::decoder_solana_core_resolve_accounts; +pub(crate) use self::core::decoder_solana_core_resolve_u8_instruction_payload; +pub(crate) use self::core::decoder_solana_core_resolve_u16_instruction_payload; +pub(crate) use self::core::decoder_solana_core_slashing_coverage; +pub(crate) use self::core::decoder_solana_core_slashing_decode; +pub(crate) use self::core::decoder_solana_core_slashing_recognize; +pub(crate) use self::core::decoder_solana_core_stake_coverage; +pub(crate) use self::core::decoder_solana_core_stake_decode; +pub(crate) use self::core::decoder_solana_core_stake_recognize; +pub(crate) use self::core::decoder_solana_core_system_coverage; +pub(crate) use self::core::decoder_solana_core_system_decode; +pub(crate) use self::core::decoder_solana_core_system_recognize; +pub(crate) use self::core::decoder_solana_core_target_outer_instruction_index; +pub(crate) use self::core::decoder_solana_core_unsupported_result; +pub(crate) use self::core::decoder_solana_core_vote_coverage; +pub(crate) use self::core::decoder_solana_core_vote_decode; +pub(crate) use self::core::decoder_solana_core_vote_recognize; +pub(crate) use self::core::decoder_solana_core_zk_elgamal_coverage; +pub(crate) use self::core::decoder_solana_core_zk_elgamal_decode; +pub(crate) use self::core::decoder_solana_core_zk_elgamal_recognize; +pub(crate) use self::core::decoder_solana_core_zk_token_proof_coverage; +pub(crate) use self::core::decoder_solana_core_zk_token_proof_decode; +pub(crate) use self::core::decoder_solana_core_zk_token_proof_recognize; /// Runtime-native Solana decoder with phased maximal native coverage. -pub use self::core::SolanaCoreDecoder; +pub use self::core::DcSolanaCoreDecoder; diff --git a/kb-lib/src/decoder/solana/core.rs b/kb-lib/src/decoder/solana/core.rs index c6203c6..86303b1 100644 --- a/kb-lib/src/decoder/solana/core.rs +++ b/kb-lib/src/decoder/solana/core.rs @@ -22,176 +22,176 @@ mod zk_elgamal; mod zk_token_proof; /// Expected role and privileges for one positional instruction account. -pub(crate) use self::accounts::AccountRole as SolanaCoreAccountRole; +pub(crate) use self::accounts::DcSolanaCoreAccountRole; /// Resolves positional instruction accounts and validates their core indexes. -pub(crate) use self::accounts::resolve_accounts as solana_core_resolve_accounts; +pub(crate) use self::accounts::decoder_solana_core_resolve_accounts; /// Returns declared Address Lookup Table instruction coverage. -pub(crate) use self::address_lookup_table::address_lookup_table_coverage as solana_core_address_lookup_table_coverage; +pub(crate) use self::address_lookup_table::decoder_solana_core_address_lookup_table_coverage; /// Decodes one Address Lookup Table instruction. -pub(crate) use self::address_lookup_table::address_lookup_table_decode as solana_core_address_lookup_table_decode; +pub(crate) use self::address_lookup_table::decoder_solana_core_address_lookup_table_decode; /// Recognizes one Address Lookup Table instruction without producing an event. -pub(crate) use self::address_lookup_table::address_lookup_table_recognize as solana_core_address_lookup_table_recognize; +pub(crate) use self::address_lookup_table::decoder_solana_core_address_lookup_table_recognize; /// Returns declared Compute Budget instruction coverage. -pub(crate) use self::compute_budget::compute_budget_coverage as solana_core_compute_budget_coverage; +pub(crate) use self::compute_budget::decoder_solana_core_compute_budget_coverage; /// Decodes one Compute Budget instruction. -pub(crate) use self::compute_budget::compute_budget_decode as solana_core_compute_budget_decode; +pub(crate) use self::compute_budget::decoder_solana_core_compute_budget_decode; /// Recognizes one Compute Budget instruction without producing an event. -pub(crate) use self::compute_budget::compute_budget_recognize as solana_core_compute_budget_recognize; +pub(crate) use self::compute_budget::decoder_solana_core_compute_budget_recognize; /// Returns declared Config Program instruction coverage. -pub(crate) use self::config::config_coverage as solana_core_config_coverage; +pub(crate) use self::config::decoder_solana_core_config_coverage; /// Decodes one generic Config Program store instruction. -pub(crate) use self::config::config_decode as solana_core_config_decode; +pub(crate) use self::config::decoder_solana_core_config_decode; /// Recognizes one generic Config Program store instruction. -pub(crate) use self::config::config_recognize as solana_core_config_recognize; +pub(crate) use self::config::decoder_solana_core_config_recognize; /// Stable Address Lookup Table surface code. -pub(crate) use self::constants::ADDRESS_LOOKUP_TABLE_SURFACE_CODE as SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE; /// Stable deprecated immutable BPF Loader surface code. -pub(crate) use self::constants::BPF_LOADER_DEPRECATED_SURFACE_CODE as SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE; /// Stable immutable BPF Loader v2 surface code. -pub(crate) use self::constants::BPF_LOADER_SURFACE_CODE as SOLANA_CORE_BPF_LOADER_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_BPF_LOADER_SURFACE_CODE; /// Stable upgradeable BPF Loader surface code. -pub(crate) use self::constants::BPF_LOADER_UPGRADEABLE_SURFACE_CODE as SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE; /// Stable Compute Budget surface code. -pub(crate) use self::constants::COMPUTE_BUDGET_SURFACE_CODE as SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE; /// Stable Config Program surface code. -pub(crate) use self::constants::CONFIG_SURFACE_CODE as SOLANA_CORE_CONFIG_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_CONFIG_SURFACE_CODE; /// Byte length of an Ed25519 public key. -pub(crate) use self::constants::ED25519_PUBLIC_KEY_BYTES as SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES; /// Stable Ed25519 signature precompile surface code. -pub(crate) use self::constants::ED25519_SURFACE_CODE as SOLANA_CORE_ED25519_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_ED25519_SURFACE_CODE; /// Stable Feature Gate surface code. -pub(crate) use self::constants::FEATURE_SURFACE_CODE as SOLANA_CORE_FEATURE_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_FEATURE_SURFACE_CODE; /// Stable Loader v4 surface code. -pub(crate) use self::constants::LOADER_V4_SURFACE_CODE as SOLANA_CORE_LOADER_V4_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE; /// Maximum retained native instruction payload accepted by the first decoder phase. -pub(crate) use self::constants::MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES as SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES; /// Current native event payload contract version. -pub(crate) use self::constants::NATIVE_EVENT_VERSION as SOLANA_CORE_NATIVE_EVENT_VERSION; +pub(crate) use self::constants::DC_SOLANA_CORE_NATIVE_EVENT_VERSION; /// Stable Native Loader surface code. -pub(crate) use self::constants::NATIVE_LOADER_SURFACE_CODE as SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE; /// Maximum number of component bytes retained as a hexadecimal event prefix. -pub(crate) use self::constants::PRECOMPILE_COMPONENT_PREFIX_BYTES as SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES; /// Stable protocol code shared by native Solana events. -pub(crate) use self::constants::PROTOCOL_CODE as SOLANA_CORE_PROTOCOL_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_PROTOCOL_CODE; /// Byte length of a secp256k1 Ethereum address. -pub(crate) use self::constants::SECP256K1_ETHEREUM_ADDRESS_BYTES as SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; /// Stable secp256k1 signature precompile surface code. -pub(crate) use self::constants::SECP256K1_SURFACE_CODE as SOLANA_CORE_SECP256K1_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE; /// Runtime maximum number of secp256r1 signatures in one precompile instruction. -pub(crate) use self::constants::SECP256R1_MAX_SIGNATURES as SOLANA_CORE_SECP256R1_MAX_SIGNATURES; +pub(crate) use self::constants::DC_SOLANA_CORE_SECP256R1_MAX_SIGNATURES; /// Byte length of a compressed secp256r1 public key. -pub(crate) use self::constants::SECP256R1_PUBLIC_KEY_BYTES as SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES; /// Stable secp256r1 signature precompile surface code. -pub(crate) use self::constants::SECP256R1_SURFACE_CODE as SOLANA_CORE_SECP256R1_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_SECP256R1_SURFACE_CODE; /// Byte length shared by compact Ed25519, secp256k1 and secp256r1 signatures. -pub(crate) use self::constants::SIGNATURE_BYTES as SOLANA_CORE_SIGNATURE_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_SIGNATURE_BYTES; /// Stable Slashing Program decoder surface code. -pub(crate) use self::constants::SLASHING_SURFACE_CODE as SOLANA_CORE_SLASHING_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_SLASHING_SURFACE_CODE; /// Stable Stake Program surface code. -pub(crate) use self::constants::STAKE_SURFACE_CODE as SOLANA_CORE_STAKE_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_STAKE_SURFACE_CODE; /// Stable System Program surface code. -pub(crate) use self::constants::SYSTEM_SURFACE_CODE as SOLANA_CORE_SYSTEM_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE; /// Canonical tracing target for the Solana Core decoder component. -pub(crate) use self::constants::TRACING_TARGET as SOLANA_CORE_TRACING_TARGET; +pub(crate) use self::constants::DC_SOLANA_CORE_TRACING_TARGET; /// Byte length of one secp256k1 offsets entry. -pub(crate) use self::constants::U8_OFFSETS_BYTES as SOLANA_CORE_U8_OFFSETS_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_U8_OFFSETS_BYTES; /// Byte length of one Ed25519 or secp256r1 offsets entry. -pub(crate) use self::constants::U16_OFFSETS_BYTES as SOLANA_CORE_U16_OFFSETS_BYTES; +pub(crate) use self::constants::DC_SOLANA_CORE_U16_OFFSETS_BYTES; /// Stable Vote Program surface code. -pub(crate) use self::constants::VOTE_SURFACE_CODE as SOLANA_CORE_VOTE_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_VOTE_SURFACE_CODE; /// Stable native ZK ElGamal Proof surface code. -pub(crate) use self::constants::ZK_ELGAMAL_PROOF_SURFACE_CODE as SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE; /// Stable historical ZK Token Proof surface code. -pub(crate) use self::constants::ZK_TOKEN_PROOF_SURFACE_CODE as SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE; +pub(crate) use self::constants::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE; /// Builds one exact decoded native observation. -pub(crate) use self::event::decoded_result as solana_core_decoded_result; +pub(crate) use self::event::decoder_solana_core_decoded_result; /// Builds one failed native decode result. -pub(crate) use self::event::failed_result as solana_core_failed_result; +pub(crate) use self::event::decoder_solana_core_failed_result; /// Builds one unsupported native decode result with a bounded diagnostic. -pub(crate) use self::event::unsupported_result as solana_core_unsupported_result; +pub(crate) use self::event::decoder_solana_core_unsupported_result; /// Returns declared Feature Gate instruction coverage. -pub(crate) use self::feature::feature_coverage as solana_core_feature_coverage; +pub(crate) use self::feature::decoder_solana_core_feature_coverage; /// Decodes one Feature Gate instruction. -pub(crate) use self::feature::feature_decode as solana_core_feature_decode; +pub(crate) use self::feature::decoder_solana_core_feature_decode; /// Recognizes one Feature Gate instruction without producing an event. -pub(crate) use self::feature::feature_recognize as solana_core_feature_recognize; +pub(crate) use self::feature::decoder_solana_core_feature_recognize; /// Returns declared loader instruction coverage. -pub(crate) use self::loaders::loaders_coverage as solana_core_loaders_coverage; +pub(crate) use self::loaders::decoder_solana_core_loaders_coverage; /// Decodes one loader instruction. -pub(crate) use self::loaders::loaders_decode as solana_core_loaders_decode; +pub(crate) use self::loaders::decoder_solana_core_loaders_decode; /// Recognizes one loader instruction without producing an event. -pub(crate) use self::loaders::loaders_recognize as solana_core_loaders_recognize; +pub(crate) use self::loaders::decoder_solana_core_loaders_recognize; /// One resolved outer instruction payload and its provenance relative to the target instruction. -pub(crate) use self::payload::ResolvedInstructionPayload as SolanaCoreResolvedInstructionPayload; +pub(crate) use self::payload::DcSolanaCoreResolvedInstructionPayload; /// Returns a hexadecimal prefix no longer than the available byte slice. -pub(crate) use self::payload::bounded_hexadecimal_prefix as solana_core_bounded_hexadecimal_prefix; +pub(crate) use self::payload::decoder_solana_core_bounded_hexadecimal_prefix; /// Extracts one exact bounded byte slice with checked arithmetic. -pub(crate) use self::payload::bounded_slice as solana_core_bounded_slice; +pub(crate) use self::payload::decoder_solana_core_bounded_slice; /// Decodes one retained base64 instruction payload with an explicit byte limit. -pub(crate) use self::payload::decode_instruction_data as solana_core_decode_instruction_data; +pub(crate) use self::payload::decoder_solana_core_decode_instruction_data; /// Returns the decoded target payload length when retained and valid. -pub(crate) use self::payload::decoded_payload_length as solana_core_decoded_payload_length; +pub(crate) use self::payload::decoder_solana_core_decoded_payload_length; /// Returns the SHA-256 of the decoded target instruction data when available. -pub(crate) use self::payload::decoded_payload_sha256 as solana_core_decoded_payload_sha256; +pub(crate) use self::payload::decoder_solana_core_decoded_payload_sha256; /// Returns the lowercase SHA-256 of one bounded byte slice. -pub(crate) use self::payload::hash_bytes as solana_core_hash_bytes; +pub(crate) use self::payload::decoder_solana_core_hash_bytes; /// Returns a normalized lowercase hexadecimal prefix. -pub(crate) use self::payload::hexadecimal_prefix as solana_core_hexadecimal_prefix; +pub(crate) use self::payload::decoder_solana_core_hexadecimal_prefix; /// Returns a stable payload hash from core or computes it from retained JSON. -pub(crate) use self::payload::payload_hash as solana_core_payload_hash; +pub(crate) use self::payload::decoder_solana_core_payload_hash; /// Reads one little-endian `u32` from an exact byte range. -pub(crate) use self::payload::read_u32_le as solana_core_read_u32_le; +pub(crate) use self::payload::decoder_solana_core_read_u32_le; /// Reads one little-endian `u64` from an exact byte range. -pub(crate) use self::payload::read_u64_le as solana_core_read_u64_le; +pub(crate) use self::payload::decoder_solana_core_read_u64_le; /// Resolves a secp256k1 instruction reference. The runtime format has no current-instruction /// sentinel: every `u8` value is an explicit outer instruction index. -pub(crate) use self::payload::resolve_u8_instruction_payload as solana_core_resolve_u8_instruction_payload; +pub(crate) use self::payload::decoder_solana_core_resolve_u8_instruction_payload; /// Resolves an Ed25519 or secp256r1 instruction reference using the official `u16::MAX` sentinel. -pub(crate) use self::payload::resolve_u16_instruction_payload as solana_core_resolve_u16_instruction_payload; +pub(crate) use self::payload::decoder_solana_core_resolve_u16_instruction_payload; /// Returns the numeric outer index of the target instruction. -pub(crate) use self::payload::target_outer_instruction_index as solana_core_target_outer_instruction_index; +pub(crate) use self::payload::decoder_solana_core_target_outer_instruction_index; /// Returns declared signature precompile coverage. -pub(crate) use self::precompiles::precompiles_coverage as solana_core_precompiles_coverage; +pub(crate) use self::precompiles::decoder_solana_core_precompiles_coverage; /// Decodes one signature precompile instruction structurally without cryptographic recomputation. -pub(crate) use self::precompiles::precompiles_decode as solana_core_precompiles_decode; +pub(crate) use self::precompiles::decoder_solana_core_precompiles_decode; /// Recognizes one signature precompile instruction without resolving referenced data. -pub(crate) use self::precompiles::precompiles_recognize as solana_core_precompiles_recognize; +pub(crate) use self::precompiles::decoder_solana_core_precompiles_recognize; /// Returns declared Slashing Program instruction coverage. -pub(crate) use self::slashing::slashing_coverage as solana_core_slashing_coverage; +pub(crate) use self::slashing::decoder_solana_core_slashing_coverage; /// Decodes one Slashing Program instruction. -pub(crate) use self::slashing::slashing_decode as solana_core_slashing_decode; +pub(crate) use self::slashing::decoder_solana_core_slashing_decode; /// Recognizes one Slashing Program instruction without producing an event. -pub(crate) use self::slashing::slashing_recognize as solana_core_slashing_recognize; +pub(crate) use self::slashing::decoder_solana_core_slashing_recognize; /// Returns declared Stake Program instruction coverage. -pub(crate) use self::stake::stake_coverage as solana_core_stake_coverage; +pub(crate) use self::stake::decoder_solana_core_stake_coverage; /// Decodes one Stake Program instruction. -pub(crate) use self::stake::stake_decode as solana_core_stake_decode; +pub(crate) use self::stake::decoder_solana_core_stake_decode; /// Recognizes one Stake Program instruction without producing an event. -pub(crate) use self::stake::stake_recognize as solana_core_stake_recognize; +pub(crate) use self::stake::decoder_solana_core_stake_recognize; /// Returns declared System Program instruction coverage. -pub(crate) use self::system::system_coverage as solana_core_system_coverage; +pub(crate) use self::system::decoder_solana_core_system_coverage; /// Decodes one System Program instruction. -pub(crate) use self::system::system_decode as solana_core_system_decode; +pub(crate) use self::system::decoder_solana_core_system_decode; /// Recognizes one System Program instruction without producing an event. -pub(crate) use self::system::system_recognize as solana_core_system_recognize; +pub(crate) use self::system::decoder_solana_core_system_recognize; /// Returns declared Vote Program instruction coverage. -pub(crate) use self::vote::vote_coverage as solana_core_vote_coverage; +pub(crate) use self::vote::decoder_solana_core_vote_coverage; /// Decodes one Vote Program instruction. -pub(crate) use self::vote::vote_decode as solana_core_vote_decode; +pub(crate) use self::vote::decoder_solana_core_vote_decode; /// Recognizes one Vote Program instruction without producing an event. -pub(crate) use self::vote::vote_recognize as solana_core_vote_recognize; +pub(crate) use self::vote::decoder_solana_core_vote_recognize; /// Returns declared ZK ElGamal Proof instruction coverage. -pub(crate) use self::zk_elgamal::zk_elgamal_coverage as solana_core_zk_elgamal_coverage; +pub(crate) use self::zk_elgamal::decoder_solana_core_zk_elgamal_coverage; /// Decodes one native ZK ElGamal Proof instruction without recomputing the proof. -pub(crate) use self::zk_elgamal::zk_elgamal_decode as solana_core_zk_elgamal_decode; +pub(crate) use self::zk_elgamal::decoder_solana_core_zk_elgamal_decode; /// Recognizes one native ZK ElGamal Proof instruction. -pub(crate) use self::zk_elgamal::zk_elgamal_recognize as solana_core_zk_elgamal_recognize; +pub(crate) use self::zk_elgamal::decoder_solana_core_zk_elgamal_recognize; /// Returns declared historical and current ZK Token Proof coverage. -pub(crate) use self::zk_token_proof::zk_token_proof_coverage as solana_core_zk_token_proof_coverage; +pub(crate) use self::zk_token_proof::decoder_solana_core_zk_token_proof_coverage; /// Decodes one historical ZK Token Proof layout without recomputing any proof. -pub(crate) use self::zk_token_proof::zk_token_proof_decode as solana_core_zk_token_proof_decode; +pub(crate) use self::zk_token_proof::decoder_solana_core_zk_token_proof_decode; /// Recognizes one historical ZK Token Proof layout or the current no-op runtime fallback. -pub(crate) use self::zk_token_proof::zk_token_proof_recognize as solana_core_zk_token_proof_recognize; +pub(crate) use self::zk_token_proof::decoder_solana_core_zk_token_proof_recognize; /// Runtime-native Solana decoder with phased maximal native coverage. -pub use self::decoder::SolanaCoreDecoder; +pub use self::decoder::DcSolanaCoreDecoder; diff --git a/kb-lib/src/decoder/solana/core/accounts.rs b/kb-lib/src/decoder/solana/core/accounts.rs index b991ef8..26d100f 100644 --- a/kb-lib/src/decoder/solana/core/accounts.rs +++ b/kb-lib/src/decoder/solana/core/accounts.rs @@ -5,7 +5,7 @@ /// Expected role and privileges for one positional instruction account. #[derive(Clone, Copy, Debug)] -pub(crate) struct AccountRole { +pub(crate) struct DcSolanaCoreAccountRole { /// Stable role code. pub(crate) role: &'static str, /// Whether the official instruction contract marks the account writable. @@ -14,7 +14,7 @@ pub(crate) struct AccountRole { pub(crate) expected_signer: std::option::Option, } -impl AccountRole { +impl DcSolanaCoreAccountRole { /// Builds one account role declaration. pub(crate) const fn new( role: &'static str, @@ -39,9 +39,9 @@ impl AccountRole { } /// Resolves positional instruction accounts and validates their core indexes. -pub(crate) fn resolve_accounts( - input: &crate::CoreInstructionReplayInput, - roles: &[crate::SolanaCoreAccountRole], +pub(crate) fn decoder_solana_core_resolve_accounts( + input: &crate::MdCoreInstructionReplayInput, + roles: &[crate::DcSolanaCoreAccountRole], minimum_count: usize, maximum_count: std::option::Option, ) -> kb_core::Result { diff --git a/kb-lib/src/decoder/solana/core/address_lookup_table.rs b/kb-lib/src/decoder/solana/core/address_lookup_table.rs index 2ddd9aa..2b11763 100644 --- a/kb-lib/src/decoder/solana/core/address_lookup_table.rs +++ b/kb-lib/src/decoder/solana/core/address_lookup_table.rs @@ -6,30 +6,31 @@ const SOURCE: &str = "solana-address-lookup-table-interface@3.1.0 ProgramInstruction wincode contract"; -const CREATE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("lookup_table", true, false), - crate::SolanaCoreAccountRole::optional_signer("authority", false), - crate::SolanaCoreAccountRole::new("payer", true, true), - crate::SolanaCoreAccountRole::new("system_program", false, false), +const CREATE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("lookup_table", true, false), + crate::DcSolanaCoreAccountRole::optional_signer("authority", false), + crate::DcSolanaCoreAccountRole::new("payer", true, true), + crate::DcSolanaCoreAccountRole::new("system_program", false, false), ]; -const AUTHORITY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("lookup_table", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), +const AUTHORITY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("lookup_table", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), ]; -const EXTEND_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("lookup_table", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), - crate::SolanaCoreAccountRole::new("payer", true, true), - crate::SolanaCoreAccountRole::new("system_program", false, false), +const EXTEND_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("lookup_table", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), + crate::DcSolanaCoreAccountRole::new("payer", true, true), + crate::DcSolanaCoreAccountRole::new("system_program", false, false), ]; -const CLOSE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("lookup_table", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), - crate::SolanaCoreAccountRole::new("recipient", true, false), +const CLOSE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("lookup_table", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), + crate::DcSolanaCoreAccountRole::new("recipient", true, false), ]; /// Returns declared Address Lookup Table instruction coverage. -pub(crate) fn address_lookup_table_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_address_lookup_table_coverage() +-> std::vec::Vec { return vec![ coverage_entry( "create_lookup_table", @@ -60,37 +61,37 @@ pub(crate) fn address_lookup_table_coverage() -> std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some( - crate::SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string(), ), std::option::Option::Some("malformed_address_lookup_table_instruction".to_string()), std::option::Option::None, ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some( - crate::SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string(), ), std::option::Option::Some("malformed_address_lookup_table_instruction".to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), ); }, }; @@ -103,39 +104,41 @@ pub(crate) fn address_lookup_table_recognize( } else { false }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( exact, priority, - std::option::Option::Some(crate::SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string()), + std::option::Option::Some( + crate::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string(), + ), entry_code.map(str::to_string).or_else(|| { return std::option::Option::Some( "unknown_address_lookup_table_instruction".to_string(), ); }), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), 4), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), 4), ); } /// Decodes one Address Lookup Table instruction. -pub(crate) fn address_lookup_table_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_address_lookup_table_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_address_lookup_table_instruction"), "address_lookup_table_payload_invalid", error.to_string(), ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_address_lookup_table_instruction"), "address_lookup_table_tag_truncated", error.to_string(), @@ -145,12 +148,12 @@ pub(crate) fn address_lookup_table_decode( let entry_code = match entry_code(tag) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_address_lookup_table_instruction", "address_lookup_table_tag_unknown", format!( "unknown Address Lookup Table instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); }, @@ -161,7 +164,7 @@ pub(crate) fn address_lookup_table_decode( let instruction = match instruction_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "address_lookup_table_wincode_invalid", format!("cannot decode exact Address Lookup Table {entry_code}: {error}"), @@ -172,9 +175,9 @@ pub(crate) fn address_lookup_table_decode( } fn decoded_instruction( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, instruction: solana_address_lookup_table_interface::instruction::ProgramInstruction, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { return match instruction { solana_address_lookup_table_interface::instruction::ProgramInstruction::CreateLookupTable { recent_slot, @@ -210,7 +213,7 @@ fn decoded_instruction( .map(std::vec::Vec::len) .unwrap_or(0); if account_count != 2 && account_count != 4 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("extend_lookup_table"), "address_lookup_table_extend_accounts_invalid", format!( @@ -259,30 +262,30 @@ fn decoded_instruction( } fn build( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, entry_code: &str, - roles: &[crate::SolanaCoreAccountRole], + roles: &[crate::DcSolanaCoreAccountRole], minimum_count: usize, maximum_count: std::option::Option, parameters: serde_json::Value, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let accounts_result = - crate::solana_core_resolve_accounts(input, roles, minimum_count, maximum_count); + crate::decoder_solana_core_resolve_accounts(input, roles, minimum_count, maximum_count); let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "address_lookup_table_accounts_invalid", error.to_string(), ); }, }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE, entry_code, - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, accounts, parameters, @@ -304,19 +307,19 @@ fn entry_code(tag: u32) -> std::option::Option<&'static str> { fn coverage_entry( entry_code: &str, instruction: solana_address_lookup_table_interface::instruction::ProgramInstruction, -) -> crate::DecoderCoverageDeclaration { +) -> crate::DcApiDecoderCoverageDeclaration { let discriminator_hex = match wincode::serialize(&instruction) { std::result::Result::Ok(bytes) => { - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), 4) + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), 4) }, std::result::Result::Err(_error) => std::option::Option::None, }; - return crate::DecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::ADDRESS_LOOKUP_TABLE_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: entry_code.to_string(), discriminator_hex, historical: false, @@ -331,7 +334,7 @@ mod tests { instruction: &solana_address_lookup_table_interface::instruction::ProgramInstruction, account_count: usize, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let bytes_result = wincode::serialize(instruction); let bytes = match bytes_result { std::result::Result::Ok(value) => value, @@ -344,7 +347,7 @@ mod tests { bytes: &[u8], account_count: usize, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let encoded = base64::engine::general_purpose::STANDARD.encode(bytes); let account_keys = (0..account_count) .map(|index| { @@ -366,7 +369,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -429,12 +432,12 @@ mod tests { ), ]; for (instruction, account_count, expected) in fixtures { - let result = crate::solana_core_address_lookup_table_decode(&replay_input( + let result = crate::decoder_solana_core_address_lookup_table_decode(&replay_input( &instruction, account_count, false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -448,28 +451,30 @@ mod tests { let instruction = solana_address_lookup_table_interface::instruction::ProgramInstruction::ExtendLookupTable { new_addresses: std::vec::Vec::new(), }; - let without_funding = - crate::solana_core_address_lookup_table_decode(&replay_input(&instruction, 2, false)); - assert_eq!(without_funding.status, crate::DecoderOutcomeStatus::Decoded); - let incomplete = - crate::solana_core_address_lookup_table_decode(&replay_input(&instruction, 3, false)); - assert_eq!(incomplete.status, crate::DecoderOutcomeStatus::Failed); + let without_funding = crate::decoder_solana_core_address_lookup_table_decode( + &replay_input(&instruction, 2, false), + ); + assert_eq!(without_funding.status, crate::DcApiDecoderOutcomeStatus::Decoded); + let incomplete = crate::decoder_solana_core_address_lookup_table_decode(&replay_input( + &instruction, + 3, + false, + )); + assert_eq!(incomplete.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn truncated_unknown_and_trailing_payloads_are_distinguished() { - let truncated = crate::solana_core_address_lookup_table_decode(&replay_input_bytes( - &[0, 0, 0], - 4, - false, - )); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let unknown = crate::solana_core_address_lookup_table_decode(&replay_input_bytes( + let truncated = crate::decoder_solana_core_address_lookup_table_decode( + &replay_input_bytes(&[0, 0, 0], 4, false), + ); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let unknown = crate::decoder_solana_core_address_lookup_table_decode(&replay_input_bytes( &[255, 0, 0, 0], 0, false, )); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); let mut valid = match wincode::serialize( &solana_address_lookup_table_interface::instruction::ProgramInstruction::FreezeLookupTable, ) { @@ -477,27 +482,30 @@ mod tests { std::result::Result::Err(error) => panic!("ALT fixture serialization failed: {error}"), }; valid.push(1); - let trailing = crate::solana_core_address_lookup_table_decode(&replay_input_bytes( + let trailing = crate::decoder_solana_core_address_lookup_table_decode(&replay_input_bytes( valid.as_slice(), 2, false, )); - assert_eq!(trailing.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(trailing.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn failed_transaction_is_decoded_as_uncommitted_lifecycle_intent() { let instruction = solana_address_lookup_table_interface::instruction::ProgramInstruction::DeactivateLookupTable; - let result = - crate::solana_core_address_lookup_table_decode(&replay_input(&instruction, 2, true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_address_lookup_table_decode(&replay_input( + &instruction, + 2, + true, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!(result.observations[0].payload_json["transactionSucceeded"], false); } #[test] fn coverage_uses_official_encoder_discriminants() { - let coverage = crate::solana_core_address_lookup_table_coverage(); + let coverage = crate::decoder_solana_core_address_lookup_table_coverage(); assert_eq!(coverage.len(), 5); assert_eq!(coverage[0].discriminator_hex.as_deref(), std::option::Option::Some("00000000")); assert_eq!(coverage[4].discriminator_hex.as_deref(), std::option::Option::Some("04000000")); diff --git a/kb-lib/src/decoder/solana/core/compute_budget.rs b/kb-lib/src/decoder/solana/core/compute_budget.rs index 9375122..589c740 100644 --- a/kb-lib/src/decoder/solana/core/compute_budget.rs +++ b/kb-lib/src/decoder/solana/core/compute_budget.rs @@ -10,7 +10,8 @@ const SOURCE_HISTORICAL: &str = "solana-sdk compute_budget::ComputeBudgetInstruction RequestUnitsDeprecated"; /// Returns declared Compute Budget instruction coverage. -pub(crate) fn compute_budget_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_compute_budget_coverage() +-> std::vec::Vec { return vec![ coverage_entry("unused_reserved", "00", false), coverage_entry("request_units_deprecated", "00", true), @@ -22,19 +23,19 @@ pub(crate) fn compute_budget_coverage() -> std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some( - crate::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE.to_string(), ), std::option::Option::Some("malformed_compute_budget_instruction".to_string()), std::option::Option::None, @@ -42,26 +43,26 @@ pub(crate) fn compute_budget_recognize( }, }; let entry_code = entry_code(bytes.as_slice()); - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( entry_code.is_some(), priority, - std::option::Option::Some(crate::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE.to_string()), entry_code.map(str::to_string).or_else(|| { return std::option::Option::Some("unknown_compute_budget_instruction".to_string()); }), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), 1), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), 1), ); } /// Decodes one Compute Budget instruction. -pub(crate) fn compute_budget_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_compute_budget_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_compute_budget_instruction"), "compute_budget_payload_invalid", error.to_string(), @@ -69,18 +70,18 @@ pub(crate) fn compute_budget_decode( }, }; if bytes.is_empty() { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_compute_budget_instruction"), "compute_budget_payload_empty", "Compute Budget instruction payload is empty", ); } let accounts_result = - crate::solana_core_resolve_accounts(input, &[], 0, std::option::Option::None); + crate::decoder_solana_core_resolve_accounts(input, &[], 0, std::option::Option::None); let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( entry_code(bytes.as_slice()), "compute_budget_accounts_invalid", error.to_string(), @@ -88,26 +89,26 @@ pub(crate) fn compute_budget_decode( }, }; return match bytes[0] { - 0 if bytes.len() == 1 => crate::DecoderExecutionResult::ignored(std::option::Option::Some( - "unused_reserved".to_string(), - )), + 0 if bytes.len() == 1 => crate::DcApiDecoderExecutionResult::ignored( + std::option::Option::Some("unused_reserved".to_string()), + ), 0 if bytes.len() == 9 => { - let units_result = crate::solana_core_read_u32_le(bytes.as_slice(), 1); + let units_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 1); let units = match units_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("request_units_deprecated"), "compute_budget_request_units_truncated", error.to_string(), ); }, }; - let additional_fee_result = crate::solana_core_read_u32_le(bytes.as_slice(), 5); + let additional_fee_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 5); let additional_fee = match additional_fee_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("request_units_deprecated"), "compute_budget_request_units_truncated", error.to_string(), @@ -118,18 +119,18 @@ pub(crate) fn compute_budget_decode( parameters.insert("units".to_string(), serde_json::json!(units)); parameters.insert("additionalFee".to_string(), serde_json::json!(additional_fee)); append_transaction_profile(input, &mut parameters); - crate::solana_core_decoded_result( + crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE, + crate::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE, "request_units_deprecated", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, true, accounts, serde_json::Value::Object(parameters), SOURCE_HISTORICAL, ) }, - 0 => crate::solana_core_failed_result( + 0 => crate::decoder_solana_core_failed_result( std::option::Option::Some("request_units_deprecated"), "compute_budget_request_units_size_invalid", format!( @@ -161,26 +162,26 @@ pub(crate) fn compute_budget_decode( "set_loaded_accounts_data_size_limit", "bytes", ), - tag => crate::solana_core_unsupported_result( + tag => crate::decoder_solana_core_unsupported_result( "unknown_compute_budget_instruction", "compute_budget_tag_unknown", format!( "unknown Compute Budget instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ), }; } fn decode_u32_instruction( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], accounts: serde_json::Value, entry_code: &str, field_name: &str, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() < 5 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "compute_budget_instruction_size_invalid", format!( @@ -189,11 +190,11 @@ fn decode_u32_instruction( ), ); } - let value_result = crate::solana_core_read_u32_le(bytes, 1); + let value_result = crate::decoder_solana_core_read_u32_le(bytes, 1); let value = match value_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "compute_budget_instruction_truncated", error.to_string(), @@ -204,11 +205,11 @@ fn decode_u32_instruction( parameters.insert(field_name.to_string(), serde_json::json!(value)); append_runtime_ignored_trailing_data(&mut parameters, bytes, 5); append_transaction_profile(input, &mut parameters); - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE, + crate::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE, entry_code, - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, accounts, serde_json::Value::Object(parameters), @@ -217,14 +218,14 @@ fn decode_u32_instruction( } fn decode_u64_instruction( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], accounts: serde_json::Value, entry_code: &str, field_name: &str, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() < 9 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "compute_budget_instruction_size_invalid", format!( @@ -233,11 +234,11 @@ fn decode_u64_instruction( ), ); } - let value_result = crate::solana_core_read_u64_le(bytes, 1); + let value_result = crate::decoder_solana_core_read_u64_le(bytes, 1); let value = match value_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "compute_budget_instruction_truncated", error.to_string(), @@ -248,11 +249,11 @@ fn decode_u64_instruction( parameters.insert(field_name.to_string(), serde_json::json!(value)); append_runtime_ignored_trailing_data(&mut parameters, bytes, 9); append_transaction_profile(input, &mut parameters); - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE, + crate::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE, entry_code, - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, accounts, serde_json::Value::Object(parameters), @@ -261,13 +262,13 @@ fn decode_u64_instruction( } fn append_transaction_profile( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, parameters: &mut serde_json::Map, ) { parameters.insert("transactionProfile".to_string(), transaction_profile(input)); } -fn transaction_profile(input: &crate::CoreInstructionReplayInput) -> serde_json::Value { +fn transaction_profile(input: &crate::MdCoreInstructionReplayInput) -> serde_json::Value { let target_path = input.instruction_path.as_str(); let mut instruction_rows = std::vec::Vec::new(); let mut effective = serde_json::Map::new(); @@ -337,7 +338,7 @@ impl ComputeBudgetProfileRow { } fn compute_budget_outer_rows( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, ) -> std::vec::Vec { let mut rows = std::vec::Vec::new(); let outer_values = match input.outer_instructions_json.as_array() { @@ -393,14 +394,14 @@ fn compute_budget_outer_rows( )); } if rows.is_empty() && input.program_id == kb_program_ids::COMPUTE_BUDGET_PROGRAM_ID { - let bytes_result = crate::solana_core_decode_instruction_data(input); + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { rows.push(profile_failure_row( input.instruction_path.parse::().unwrap_or(0), input.instruction_path.clone(), - serde_json::Value::String(crate::solana_core_payload_hash(input)), + serde_json::Value::String(crate::decoder_solana_core_payload_hash(input)), "payload_invalid", error.to_string().as_str(), )); @@ -410,7 +411,7 @@ fn compute_budget_outer_rows( rows.push(profile_row_from_bytes( input.instruction_path.parse::().unwrap_or(0), input.instruction_path.clone(), - serde_json::Value::String(crate::solana_core_payload_hash(input)), + serde_json::Value::String(crate::decoder_solana_core_payload_hash(input)), bytes.as_slice(), )); } @@ -432,10 +433,14 @@ fn profile_row_from_bytes( "unused_reserved" => {}, "request_units_deprecated" => { if bytes.len() == 9 { - if let std::result::Result::Ok(value) = crate::solana_core_read_u32_le(bytes, 1) { + if let std::result::Result::Ok(value) = + crate::decoder_solana_core_read_u32_le(bytes, 1) + { parameters.insert("units".to_string(), serde_json::json!(value)); } - if let std::result::Result::Ok(value) = crate::solana_core_read_u32_le(bytes, 5) { + if let std::result::Result::Ok(value) = + crate::decoder_solana_core_read_u32_le(bytes, 5) + { parameters.insert("additionalFee".to_string(), serde_json::json!(value)); } } else { @@ -445,7 +450,9 @@ fn profile_row_from_bytes( }, "request_heap_frame" | "set_compute_unit_limit" | "set_loaded_accounts_data_size_limit" => { if bytes.len() >= 5 { - if let std::result::Result::Ok(value) = crate::solana_core_read_u32_le(bytes, 1) { + if let std::result::Result::Ok(value) = + crate::decoder_solana_core_read_u32_le(bytes, 1) + { let field_name = match entry { "request_heap_frame" => "bytes", "set_compute_unit_limit" => "computeUnitLimit", @@ -461,7 +468,9 @@ fn profile_row_from_bytes( }, "set_compute_unit_price" => { if bytes.len() >= 9 { - if let std::result::Result::Ok(value) = crate::solana_core_read_u64_le(bytes, 1) { + if let std::result::Result::Ok(value) = + crate::decoder_solana_core_read_u64_le(bytes, 1) + { parameters.insert("microLamports".to_string(), serde_json::json!(value)); } trailing_data_present = bytes.len() > 9; @@ -515,7 +524,7 @@ fn decode_payload_json_for_profile( return std::result::Result::Err("payload does not contain dataBase64".to_string()); }, }; - let maximum_encoded_length = crate::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES + let maximum_encoded_length = crate::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES .saturating_mul(4) .saturating_div(3) .saturating_add(4); @@ -531,10 +540,10 @@ fn decode_payload_json_for_profile( return std::result::Result::Err(format!("payload is not valid base64: {error}")); }, }; - if decoded.len() > crate::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES { + if decoded.len() > crate::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES { return std::result::Result::Err(format!( "payload exceeds {} decoded bytes", - crate::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES + crate::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES )); } return std::result::Result::Ok(decoded); @@ -612,11 +621,11 @@ fn append_runtime_ignored_trailing_data( parameters.insert("trailingDataByteLength".to_string(), serde_json::json!(trailing_data.len())); parameters.insert( "trailingDataSha256".to_string(), - serde_json::json!(crate::solana_core_hash_bytes(trailing_data)), + serde_json::json!(crate::decoder_solana_core_hash_bytes(trailing_data)), ); parameters.insert( "trailingDataPrefixHex".to_string(), - serde_json::json!(crate::solana_core_hexadecimal_prefix( + serde_json::json!(crate::decoder_solana_core_hexadecimal_prefix( trailing_data, trailing_data.len().min(16), )), @@ -647,13 +656,13 @@ fn coverage_entry( entry_code: &str, discriminator_hex: &str, historical: bool, -) -> crate::DecoderCoverageDeclaration { - return crate::DecoderCoverageDeclaration { +) -> crate::DcApiDecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::COMPUTE_BUDGET_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: entry_code.to_string(), discriminator_hex: std::option::Option::Some(discriminator_hex.to_string()), historical, @@ -664,9 +673,9 @@ fn coverage_entry( mod tests { use base64::Engine; // rust-rules: trait-import - fn replay_input(bytes: &[u8], transaction_failed: bool) -> crate::CoreInstructionReplayInput { + fn replay_input(bytes: &[u8], transaction_failed: bool) -> crate::MdCoreInstructionReplayInput { let encoded = base64::engine::general_purpose::STANDARD.encode(bytes); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -697,9 +706,9 @@ mod tests { bytes: &[u8], instruction_path: &str, outer_instructions_json: serde_json::Value, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let encoded = base64::engine::general_purpose::STANDARD.encode(bytes); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -761,12 +770,12 @@ mod tests { &[2, 128, 132, 30, 0], ), ]); - let result = crate::solana_core_compute_budget_decode(&replay_input_with_outer( + let result = crate::decoder_solana_core_compute_budget_decode(&replay_input_with_outer( &[2, 64, 66, 15, 0], "0", outer, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let profile = &result.observations[0].payload_json["parameters"]["transactionProfile"]; assert_eq!(profile["currentInstructionIsProfileEmitter"], true); assert_eq!(profile["computeBudgetInstructionCount"], 3); @@ -790,9 +799,11 @@ mod tests { }, }; assert_eq!(bytes, [3, 7, 0, 0, 0, 0, 0, 0, 0]); - let result = - crate::solana_core_compute_budget_decode(&replay_input(bytes.as_slice(), false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_compute_budget_decode(&replay_input( + bytes.as_slice(), + false, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("set_compute_unit_price") @@ -808,9 +819,11 @@ mod tests { (vec![4, 0, 0, 0, 1], "set_loaded_accounts_data_size_limit"), ]; for (bytes, expected) in fixtures { - let result = - crate::solana_core_compute_budget_decode(&replay_input(bytes.as_slice(), false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_compute_budget_decode(&replay_input( + bytes.as_slice(), + false, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -821,11 +834,11 @@ mod tests { #[test] fn historical_request_units_is_decoded() { - let result = crate::solana_core_compute_budget_decode(&replay_input( + let result = crate::decoder_solana_core_compute_budget_decode(&replay_input( &[0, 64, 13, 3, 0, 7, 0, 0, 0], false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("request_units_deprecated") @@ -836,27 +849,28 @@ mod tests { #[test] fn reserved_unused_tag_is_ignored_without_false_event() { - let result = crate::solana_core_compute_budget_decode(&replay_input(&[0], false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Ignored); + let result = crate::decoder_solana_core_compute_budget_decode(&replay_input(&[0], false)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Ignored); assert!(result.observations.is_empty()); } #[test] fn truncated_and_unknown_payloads_are_distinguished() { - let truncated = crate::solana_core_compute_budget_decode(&replay_input(&[2, 1, 2], false)); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + let truncated = + crate::decoder_solana_core_compute_budget_decode(&replay_input(&[2, 1, 2], false)); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let unknown = - crate::solana_core_compute_budget_decode(&replay_input(&[255, 1, 2, 3], false)); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); + crate::decoder_solana_core_compute_budget_decode(&replay_input(&[255, 1, 2, 3], false)); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); } #[test] fn current_variants_accept_and_preserve_runtime_ignored_trailing_bytes() { - let result = crate::solana_core_compute_budget_decode(&replay_input( + let result = crate::decoder_solana_core_compute_budget_decode(&replay_input( &[2, 64, 13, 3, 0, 1, 2, 3, 4, 5, 6, 7], true, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("set_compute_unit_limit") @@ -877,9 +891,11 @@ mod tests { #[test] fn failed_transaction_event_is_not_committed() { - let result = - crate::solana_core_compute_budget_decode(&replay_input(&[2, 64, 13, 3, 0], true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_compute_budget_decode(&replay_input( + &[2, 64, 13, 3, 0], + true, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(result.observations[0].transaction_failed); assert!(!result.observations[0].observation_committed); assert_eq!(result.observations[0].payload_json["transactionSucceeded"], false); @@ -887,7 +903,7 @@ mod tests { #[test] fn coverage_declares_current_and_historical_entries() { - let coverage = crate::solana_core_compute_budget_coverage(); + let coverage = crate::decoder_solana_core_compute_budget_coverage(); assert_eq!(coverage.len(), 6); assert!(coverage.iter().any(|entry| { return entry.entry_code == "request_units_deprecated" && entry.historical; diff --git a/kb-lib/src/decoder/solana/core/config.rs b/kb-lib/src/decoder/solana/core/config.rs index a50ec7d..23c5fb8 100644 --- a/kb-lib/src/decoder/solana/core/config.rs +++ b/kb-lib/src/decoder/solana/core/config.rs @@ -14,11 +14,14 @@ struct ParsedConfigPayload { } /// Returns declared Config Program instruction coverage. -pub(crate) fn config_coverage() -> std::vec::Vec { - return vec![crate::DecoderCoverageDeclaration { +pub(crate) fn decoder_solana_core_config_coverage() +-> std::vec::Vec { + return vec![crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::CONFIG_PROGRAM_ID.to_string(), - surface_code: std::option::Option::Some(crate::SOLANA_CORE_CONFIG_SURFACE_CODE.to_string()), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + surface_code: std::option::Option::Some( + crate::DC_SOLANA_CORE_CONFIG_SURFACE_CODE.to_string(), + ), + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: "store".to_string(), discriminator_hex: std::option::Option::None, historical: false, @@ -26,46 +29,46 @@ pub(crate) fn config_coverage() -> std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_CONFIG_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_CONFIG_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_config_store".to_string()), std::option::Option::None, ); }, }; let exact = parse_payload(bytes.as_slice()).is_ok(); - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( exact, priority, - std::option::Option::Some(crate::SOLANA_CORE_CONFIG_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_CONFIG_SURFACE_CODE.to_string()), std::option::Option::Some(if exact { "store".to_string() } else { "malformed_config_store".to_string() }), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(3)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(3)), ); } /// Decodes one generic Config Program store instruction. -pub(crate) fn config_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_config_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_config_store"), "config_payload_invalid", error.to_string(), @@ -76,7 +79,7 @@ pub(crate) fn config_decode( let parsed = match parsed_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("store"), "config_keys_invalid", error.to_string(), @@ -87,7 +90,7 @@ pub(crate) fn config_decode( let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("store"), "config_accounts_invalid", error.to_string(), @@ -97,7 +100,7 @@ pub(crate) fn config_decode( let data = match bytes.get(parsed.data_offset..) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("store"), "config_data_offset_invalid", "Config data offset exceeds retained payload", @@ -112,11 +115,11 @@ pub(crate) fn config_decode( }) .collect::>(); let signer_count = parsed.keys.iter().filter(|(_, signer)| return *signer).count(); - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_CONFIG_SURFACE_CODE, + crate::DC_SOLANA_CORE_CONFIG_SURFACE_CODE, "store", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, accounts, serde_json::json!({ @@ -124,8 +127,8 @@ pub(crate) fn config_decode( "configuredKeyCount": parsed.keys.len(), "configuredSignerCount": signer_count, "configDataByteLength": data.len(), - "configDataSha256": crate::solana_core_hash_bytes(data), - "configDataPrefixHex": crate::solana_core_hexadecimal_prefix(data, data.len().min(16)), + "configDataSha256": crate::decoder_solana_core_hash_bytes(data), + "configDataPrefixHex": crate::decoder_solana_core_hexadecimal_prefix(data, data.len().min(16)), "configDataSemantics": "opaque_program_specific", }), SOURCE, @@ -247,7 +250,7 @@ fn read_compact_u16(bytes: &[u8]) -> kb_core::Result<(u16, usize)> { } fn resolve_and_validate_accounts( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, parsed: &ParsedConfigPayload, ) -> kb_core::Result { let instruction_accounts = match input.instruction_accounts_json.as_array() { @@ -277,12 +280,12 @@ fn resolve_and_validate_accounts( .map(|(pubkey, _signer)| return pubkey.as_str()) .collect::>(); let mut roles = std::vec::Vec::with_capacity(required_signers.len().saturating_add(1)); - roles.push(crate::SolanaCoreAccountRole::optional_signer("config_account", true)); + roles.push(crate::DcSolanaCoreAccountRole::optional_signer("config_account", true)); for _signer in &required_signers { - roles.push(crate::SolanaCoreAccountRole::new("configured_signer", true, true)); + roles.push(crate::DcSolanaCoreAccountRole::new("configured_signer", true, true)); } let minimum_count = required_signers.len().saturating_add(1); - let accounts = match crate::solana_core_resolve_accounts( + let accounts = match crate::decoder_solana_core_resolve_accounts( input, roles.as_slice(), minimum_count, @@ -338,7 +341,7 @@ mod tests { bytes: &[u8], extra_accounts: &[std::string::String], transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let mut keys = vec!["ConfigAccount1111111111111111111111111111".to_string()]; keys.extend_from_slice(extra_accounts); let account_keys = keys @@ -362,7 +365,7 @@ mod tests { return serde_json::json!({"accountIndex": index, "accountKey": key}); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -395,11 +398,12 @@ mod tests { fn valid_generic_store_is_recognized_exactly() { let payload = encode_payload(&[], &[1, 2, 3]); let input = replay_input(payload.as_slice(), &[], false); - let recognition = crate::solana_core_config_recognize(&input, 100); + let recognition = crate::decoder_solana_core_config_recognize(&input, 100); assert!(recognition.compatible); assert!(recognition.exact); assert_eq!(recognition.entry_code.as_deref(), std::option::Option::Some("store")); - let malformed = crate::solana_core_config_recognize(&replay_input(&[], &[], false), 100); + let malformed = + crate::decoder_solana_core_config_recognize(&replay_input(&[], &[], false), 100); assert!(malformed.compatible); assert!(!malformed.exact); } @@ -408,8 +412,8 @@ mod tests { fn empty_key_set_and_opaque_data_decode_without_invented_semantics() { let payload = encode_payload(&[], &[1, 2, 3, 4]); let result = - crate::solana_core_config_decode(&replay_input(payload.as_slice(), &[], false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + crate::decoder_solana_core_config_decode(&replay_input(payload.as_slice(), &[], false)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations[0].payload_json["parameters"]["configuredKeyCount"], 0); assert_eq!(result.observations[0].payload_json["parameters"]["configDataByteLength"], 4); assert_eq!( @@ -423,9 +427,12 @@ mod tests { let signer_bytes = [7_u8; 32]; let signer = bs58::encode(signer_bytes).into_string(); let payload = encode_payload(&[([3_u8; 32], false), (signer_bytes, true)], &[9]); - let result = - crate::solana_core_config_decode(&replay_input(payload.as_slice(), &[signer], false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_config_decode(&replay_input( + payload.as_slice(), + &[signer], + false, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations[0].payload_json["parameters"]["configuredSignerCount"], 1); assert_eq!(result.observations[0].payload_json["accounts"][1]["role"], "configured_signer"); } @@ -452,9 +459,12 @@ mod tests { value }, ] { - let result = - crate::solana_core_config_decode(&replay_input(payload.as_slice(), &[], false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = crate::decoder_solana_core_config_decode(&replay_input( + payload.as_slice(), + &[], + false, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -463,27 +473,28 @@ mod tests { let signer_bytes = [8_u8; 32]; let payload = encode_payload(&[(signer_bytes, true)], &[]); let missing = - crate::solana_core_config_decode(&replay_input(payload.as_slice(), &[], false)); - assert_eq!(missing.status, crate::DecoderOutcomeStatus::Failed); - let mismatch = crate::solana_core_config_decode(&replay_input( + crate::decoder_solana_core_config_decode(&replay_input(payload.as_slice(), &[], false)); + assert_eq!(missing.status, crate::DcApiDecoderOutcomeStatus::Failed); + let mismatch = crate::decoder_solana_core_config_decode(&replay_input( payload.as_slice(), &[bs58::encode([9_u8; 32]).into_string()], false, )); - assert_eq!(mismatch.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(mismatch.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn failed_config_store_is_decoded_as_uncommitted_intent() { let payload = encode_payload(&[], &[5]); - let result = crate::solana_core_config_decode(&replay_input(payload.as_slice(), &[], true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = + crate::decoder_solana_core_config_decode(&replay_input(payload.as_slice(), &[], true)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); } #[test] fn coverage_declares_one_generic_store_surface() { - let coverage = crate::solana_core_config_coverage(); + let coverage = crate::decoder_solana_core_config_coverage(); assert_eq!(coverage.len(), 1); assert_eq!(coverage[0].entry_code, "store"); assert!(coverage[0].discriminator_hex.is_none()); diff --git a/kb-lib/src/decoder/solana/core/constants.rs b/kb-lib/src/decoder/solana/core/constants.rs index e7fda41..38f0d09 100644 --- a/kb-lib/src/decoder/solana/core/constants.rs +++ b/kb-lib/src/decoder/solana/core/constants.rs @@ -4,63 +4,67 @@ //! Local constants for the Solana Core decoder component. /// Stable protocol code shared by native Solana events. -pub(crate) const PROTOCOL_CODE: &str = "solana_native"; +pub(crate) const DC_SOLANA_CORE_PROTOCOL_CODE: &str = "solana_native"; /// Stable System Program surface code. -pub(crate) const SYSTEM_SURFACE_CODE: &str = "solana_native_system"; +pub(crate) const DC_SOLANA_CORE_SYSTEM_SURFACE_CODE: &str = "solana_native_system"; /// Stable deprecated immutable BPF Loader surface code. -pub(crate) const BPF_LOADER_DEPRECATED_SURFACE_CODE: &str = "solana_native_bpf_loader_deprecated"; +pub(crate) const DC_SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE: &str = + "solana_native_bpf_loader_deprecated"; /// Stable immutable BPF Loader v2 surface code. -pub(crate) const BPF_LOADER_SURFACE_CODE: &str = "solana_native_bpf_loader"; +pub(crate) const DC_SOLANA_CORE_BPF_LOADER_SURFACE_CODE: &str = "solana_native_bpf_loader"; /// Stable upgradeable BPF Loader surface code. -pub(crate) const BPF_LOADER_UPGRADEABLE_SURFACE_CODE: &str = "solana_native_bpf_loader_upgradeable"; +pub(crate) const DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE: &str = + "solana_native_bpf_loader_upgradeable"; /// Stable Loader v4 surface code. -pub(crate) const LOADER_V4_SURFACE_CODE: &str = "solana_native_loader_v4"; +pub(crate) const DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE: &str = "solana_native_loader_v4"; /// Stable Native Loader surface code. -pub(crate) const NATIVE_LOADER_SURFACE_CODE: &str = "solana_native_loader"; +pub(crate) const DC_SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE: &str = "solana_native_loader"; /// Stable Compute Budget surface code. -pub(crate) const COMPUTE_BUDGET_SURFACE_CODE: &str = "solana_native_compute_budget"; +pub(crate) const DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE: &str = "solana_native_compute_budget"; /// Stable Address Lookup Table surface code. -pub(crate) const ADDRESS_LOOKUP_TABLE_SURFACE_CODE: &str = "solana_native_address_lookup_table"; +pub(crate) const DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE: &str = + "solana_native_address_lookup_table"; /// Stable Vote Program surface code. -pub(crate) const VOTE_SURFACE_CODE: &str = "solana_native_vote"; +pub(crate) const DC_SOLANA_CORE_VOTE_SURFACE_CODE: &str = "solana_native_vote"; /// Stable Stake Program surface code. -pub(crate) const STAKE_SURFACE_CODE: &str = "solana_native_stake"; +pub(crate) const DC_SOLANA_CORE_STAKE_SURFACE_CODE: &str = "solana_native_stake"; /// Stable Config Program surface code. -pub(crate) const CONFIG_SURFACE_CODE: &str = "solana_native_config"; +pub(crate) const DC_SOLANA_CORE_CONFIG_SURFACE_CODE: &str = "solana_native_config"; /// Stable Feature Gate surface code. -pub(crate) const FEATURE_SURFACE_CODE: &str = "solana_native_feature"; +pub(crate) const DC_SOLANA_CORE_FEATURE_SURFACE_CODE: &str = "solana_native_feature"; /// Stable Ed25519 signature precompile surface code. -pub(crate) const ED25519_SURFACE_CODE: &str = "solana_native_ed25519"; +pub(crate) const DC_SOLANA_CORE_ED25519_SURFACE_CODE: &str = "solana_native_ed25519"; /// Stable secp256k1 signature precompile surface code. -pub(crate) const SECP256K1_SURFACE_CODE: &str = "solana_native_secp256k1"; +pub(crate) const DC_SOLANA_CORE_SECP256K1_SURFACE_CODE: &str = "solana_native_secp256k1"; /// Stable secp256r1 signature precompile surface code. -pub(crate) const SECP256R1_SURFACE_CODE: &str = "solana_native_secp256r1"; +pub(crate) const DC_SOLANA_CORE_SECP256R1_SURFACE_CODE: &str = "solana_native_secp256r1"; /// Stable native ZK ElGamal Proof surface code. -pub(crate) const ZK_ELGAMAL_PROOF_SURFACE_CODE: &str = "solana_native_zk_elgamal_proof"; +pub(crate) const DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE: &str = + "solana_native_zk_elgamal_proof"; /// Stable historical ZK Token Proof surface code. -pub(crate) const ZK_TOKEN_PROOF_SURFACE_CODE: &str = "solana_native_zk_token_proof"; +pub(crate) const DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE: &str = "solana_native_zk_token_proof"; /// Byte length shared by compact Ed25519, secp256k1 and secp256r1 signatures. -pub(crate) const SIGNATURE_BYTES: usize = 64; +pub(crate) const DC_SOLANA_CORE_SIGNATURE_BYTES: usize = 64; /// Byte length of an Ed25519 public key. -pub(crate) const ED25519_PUBLIC_KEY_BYTES: usize = 32; +pub(crate) const DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES: usize = 32; /// Byte length of a compressed secp256r1 public key. -pub(crate) const SECP256R1_PUBLIC_KEY_BYTES: usize = 33; +pub(crate) const DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES: usize = 33; /// Byte length of a secp256k1 Ethereum address. -pub(crate) const SECP256K1_ETHEREUM_ADDRESS_BYTES: usize = 20; +pub(crate) const DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES: usize = 20; /// Byte length of one Ed25519 or secp256r1 offsets entry. -pub(crate) const U16_OFFSETS_BYTES: usize = 14; +pub(crate) const DC_SOLANA_CORE_U16_OFFSETS_BYTES: usize = 14; /// Byte length of one secp256k1 offsets entry. -pub(crate) const U8_OFFSETS_BYTES: usize = 11; +pub(crate) const DC_SOLANA_CORE_U8_OFFSETS_BYTES: usize = 11; /// Stable Slashing Program decoder surface code. -pub(crate) const SLASHING_SURFACE_CODE: &str = "solana_native_slashing"; +pub(crate) const DC_SOLANA_CORE_SLASHING_SURFACE_CODE: &str = "solana_native_slashing"; /// Runtime maximum number of secp256r1 signatures in one precompile instruction. -pub(crate) const SECP256R1_MAX_SIGNATURES: usize = 8; +pub(crate) const DC_SOLANA_CORE_SECP256R1_MAX_SIGNATURES: usize = 8; /// Maximum number of component bytes retained as a hexadecimal event prefix. -pub(crate) const PRECOMPILE_COMPONENT_PREFIX_BYTES: usize = 16; +pub(crate) const DC_SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES: usize = 16; /// Maximum retained native instruction payload accepted by the first decoder phase. -pub(crate) const MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES: usize = 4_096; +pub(crate) const DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES: usize = 4_096; /// Current native event payload contract version. -pub(crate) const NATIVE_EVENT_VERSION: u32 = 1; +pub(crate) const DC_SOLANA_CORE_NATIVE_EVENT_VERSION: u32 = 1; /// Canonical tracing target for the Solana Core decoder component. -pub(crate) const TRACING_TARGET: &str = "kb-lib.decoder.solana.core"; +pub(crate) const DC_SOLANA_CORE_TRACING_TARGET: &str = "kb-lib.decoder.solana.core"; diff --git a/kb-lib/src/decoder/solana/core/decoder.rs b/kb-lib/src/decoder/solana/core/decoder.rs index 01ab852..2471630 100644 --- a/kb-lib/src/decoder/solana/core/decoder.rs +++ b/kb-lib/src/decoder/solana/core/decoder.rs @@ -3,93 +3,93 @@ //! Runtime-native Solana program classifier for the common decode pipeline. -const NATIVE_SURFACES: &[crate::DecoderSurface] = &[ - crate::DecoderSurface { +const NATIVE_SURFACES: &[crate::DcApiDecoderSurface] = &[ + crate::DcApiDecoderSurface { program_id: kb_program_ids::ADDRESS_LOOKUP_TABLE_PROGRAM_ID, surface_code: "solana_native_address_lookup_table", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::BPF_LOADER_DEPRECATED_PROGRAM_ID, surface_code: "solana_native_bpf_loader_deprecated", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::BPF_LOADER_PROGRAM_ID, surface_code: "solana_native_bpf_loader", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::BPF_LOADER_UPGRADEABLE_PROGRAM_ID, surface_code: "solana_native_bpf_loader_upgradeable", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::COMPUTE_BUDGET_PROGRAM_ID, surface_code: "solana_native_compute_budget", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::CONFIG_PROGRAM_ID, surface_code: "solana_native_config", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::ED25519_PROGRAM_ID, surface_code: "solana_native_ed25519", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::FEATURE_PROGRAM_ID, surface_code: "solana_native_feature", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::LOADER_V4_PROGRAM_ID, surface_code: "solana_native_loader_v4", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::NATIVE_LOADER_PROGRAM_ID, surface_code: "solana_native_loader", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::SECP256K1_PROGRAM_ID, surface_code: "solana_native_secp256k1", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::SECP256R1_PROGRAM_ID, surface_code: "solana_native_secp256r1", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::SLASHING_PROGRAM_ID, surface_code: "solana_native_slashing", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::STAKE_PROGRAM_ID, surface_code: "solana_native_stake", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::SYSTEM_PROGRAM_ID, surface_code: "solana_native_system", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::VOTE_PROGRAM_ID, surface_code: "solana_native_vote", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::ZK_ELGAMAL_PROOF_PROGRAM_ID, surface_code: "solana_native_zk_elgamal_proof", priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::ZK_TOKEN_PROOF_PROGRAM_ID, surface_code: "solana_native_zk_token_proof", priority: 100, @@ -119,9 +119,9 @@ const LEGACY_PROGRAM_IDS: &[&str] = &[ /// Runtime-native Solana decoder with phased maximal instruction coverage. #[derive(Clone, Debug, Default)] -pub struct SolanaCoreDecoder; +pub struct DcSolanaCoreDecoder; -impl crate::ProtocolDecoder for crate::SolanaCoreDecoder { +impl crate::DcApiProtocolDecoder for crate::DcSolanaCoreDecoder { fn decoder_name(&self) -> &'static str { return "kb_decoder_solana_core"; } @@ -136,49 +136,49 @@ impl crate::ProtocolDecoder for crate::SolanaCoreDecoder { fn supports_observation( &self, - observation: &crate::ProgramObservation, - ) -> crate::DecoderSupport { - return if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) { - crate::DecoderSupport::Maybe + observation: &crate::MdProgramObservation, + ) -> crate::DcApiDecoderSupport { + return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + crate::DcApiDecoderSupport::Maybe } else { - crate::DecoderSupport::No + crate::DcApiDecoderSupport::No }; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { - tracing::debug!(target: crate::SOLANA_CORE_TRACING_TARGET, "legacy native decoder adapter classified an observation without maximal decoding"); + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { + tracing::debug!(target: crate::DC_SOLANA_CORE_TRACING_TARGET, "legacy native decoder adapter classified an observation without maximal decoding"); return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::InstructionDecoder for crate::SolanaCoreDecoder { - fn identity(&self) -> crate::DecoderIdentity { - return crate::DecoderIdentity { +impl crate::DcApiInstructionDecoder for crate::DcSolanaCoreDecoder { + fn identity(&self) -> crate::DcApiDecoderIdentity { + return crate::DcApiDecoderIdentity { name: "solana_native_classifier".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn surfaces(&self) -> &'static [crate::DecoderSurface] { + fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] { return NATIVE_SURFACES; } - fn coverage(&self) -> std::vec::Vec { - let mut coverage = crate::solana_core_system_coverage(); - coverage.extend(crate::solana_core_compute_budget_coverage()); - coverage.extend(crate::solana_core_config_coverage()); - coverage.extend(crate::solana_core_feature_coverage()); - coverage.extend(crate::solana_core_vote_coverage()); - coverage.extend(crate::solana_core_stake_coverage()); - coverage.extend(crate::solana_core_address_lookup_table_coverage()); - coverage.extend(crate::solana_core_loaders_coverage()); - coverage.extend(crate::solana_core_precompiles_coverage()); - coverage.extend(crate::solana_core_slashing_coverage()); - coverage.extend(crate::solana_core_zk_elgamal_coverage()); - coverage.extend(crate::solana_core_zk_token_proof_coverage()); + fn coverage(&self) -> std::vec::Vec { + let mut coverage = crate::decoder_solana_core_system_coverage(); + coverage.extend(crate::decoder_solana_core_compute_budget_coverage()); + coverage.extend(crate::decoder_solana_core_config_coverage()); + coverage.extend(crate::decoder_solana_core_feature_coverage()); + coverage.extend(crate::decoder_solana_core_vote_coverage()); + coverage.extend(crate::decoder_solana_core_stake_coverage()); + coverage.extend(crate::decoder_solana_core_address_lookup_table_coverage()); + coverage.extend(crate::decoder_solana_core_loaders_coverage()); + coverage.extend(crate::decoder_solana_core_precompiles_coverage()); + coverage.extend(crate::decoder_solana_core_slashing_coverage()); + coverage.extend(crate::decoder_solana_core_zk_elgamal_coverage()); + coverage.extend(crate::decoder_solana_core_zk_token_proof_coverage()); for surface in NATIVE_SURFACES { if surface.program_id == kb_program_ids::SYSTEM_PROGRAM_ID || surface.program_id == kb_program_ids::COMPUTE_BUDGET_PROGRAM_ID @@ -195,10 +195,10 @@ impl crate::InstructionDecoder for crate::SolanaCoreDecoder { { continue; } - coverage.push(crate::DecoderCoverageDeclaration { + coverage.push(crate::DcApiDecoderCoverageDeclaration { program_id: surface.program_id.to_string(), surface_code: std::option::Option::Some(surface.surface_code.to_string()), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: "unclassified_native_instruction".to_string(), discriminator_hex: std::option::Option::None, historical: is_historical_native_program(surface.program_id), @@ -207,91 +207,98 @@ impl crate::InstructionDecoder for crate::SolanaCoreDecoder { return coverage; } - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition { - tracing::debug!(target: crate::SOLANA_CORE_TRACING_TARGET, action = "recognize", signature = %input.signature, slot = input.slot, instruction_path = %input.instruction_path, program_id = %input.program_id, input_key = %input.replay_input_key, transaction_failed = input.transaction_failed, "recognize native Solana contextual instruction"); + fn recognize( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderRecognition { + tracing::debug!(target: crate::DC_SOLANA_CORE_TRACING_TARGET, action = "recognize", signature = %input.signature, slot = input.slot, instruction_path = %input.instruction_path, program_id = %input.program_id, input_key = %input.replay_input_key, transaction_failed = input.transaction_failed, "recognize native Solana contextual instruction"); let surface = NATIVE_SURFACES .iter() .find(|surface| return surface.program_id == input.program_id); let surface = match surface { std::option::Option::Some(value) => value, std::option::Option::None => { - tracing::debug!(target: crate::SOLANA_CORE_TRACING_TARGET, action = "recognize", signature = %input.signature, instruction_path = %input.instruction_path, program_id = %input.program_id, compatible = false, "native Solana decoder does not support program id"); - return crate::DecoderRecognition::incompatible(); + tracing::debug!(target: crate::DC_SOLANA_CORE_TRACING_TARGET, action = "recognize", signature = %input.signature, instruction_path = %input.instruction_path, program_id = %input.program_id, compatible = false, "native Solana decoder does not support program id"); + return crate::DcApiDecoderRecognition::incompatible(); }, }; let recognition = if input.program_id == kb_program_ids::SYSTEM_PROGRAM_ID { - crate::solana_core_system_recognize(input, surface.priority) + crate::decoder_solana_core_system_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::COMPUTE_BUDGET_PROGRAM_ID { - crate::solana_core_compute_budget_recognize(input, surface.priority) + crate::decoder_solana_core_compute_budget_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::ADDRESS_LOOKUP_TABLE_PROGRAM_ID { - crate::solana_core_address_lookup_table_recognize(input, surface.priority) + crate::decoder_solana_core_address_lookup_table_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::CONFIG_PROGRAM_ID { - crate::solana_core_config_recognize(input, surface.priority) + crate::decoder_solana_core_config_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::FEATURE_PROGRAM_ID { - crate::solana_core_feature_recognize(input, surface.priority) + crate::decoder_solana_core_feature_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::VOTE_PROGRAM_ID { - crate::solana_core_vote_recognize(input, surface.priority) + crate::decoder_solana_core_vote_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::STAKE_PROGRAM_ID { - crate::solana_core_stake_recognize(input, surface.priority) + crate::decoder_solana_core_stake_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::SLASHING_PROGRAM_ID { - crate::solana_core_slashing_recognize(input, surface.priority) + crate::decoder_solana_core_slashing_recognize(input, surface.priority) } else if is_signature_precompile(input.program_id.as_str()) { - crate::solana_core_precompiles_recognize(input, surface.priority) + crate::decoder_solana_core_precompiles_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::ZK_ELGAMAL_PROOF_PROGRAM_ID { - crate::solana_core_zk_elgamal_recognize(input, surface.priority) + crate::decoder_solana_core_zk_elgamal_recognize(input, surface.priority) } else if input.program_id == kb_program_ids::ZK_TOKEN_PROOF_PROGRAM_ID { - crate::solana_core_zk_token_proof_recognize(input, surface.priority) + crate::decoder_solana_core_zk_token_proof_recognize(input, surface.priority) } else if is_loader_program(input.program_id.as_str()) { - crate::solana_core_loaders_recognize(input, surface.priority) + crate::decoder_solana_core_loaders_recognize(input, surface.priority) } else { - crate::DecoderRecognition::compatible( + crate::DcApiDecoderRecognition::compatible( false, surface.priority, std::option::Option::Some(surface.surface_code.to_string()), std::option::Option::Some("unclassified_native_instruction".to_string()), - crate::discriminator_8_hex(input), + crate::decoder_api_discriminator_8_hex(input), ) }; - tracing::debug!(target: crate::SOLANA_CORE_TRACING_TARGET, action = "recognize", signature = %input.signature, instruction_path = %input.instruction_path, program_id = %input.program_id, surface_code = surface.surface_code, recognition = ?recognition, compatible = true, "native Solana decoder recognized contextual instruction"); + tracing::debug!(target: crate::DC_SOLANA_CORE_TRACING_TARGET, action = "recognize", signature = %input.signature, instruction_path = %input.instruction_path, program_id = %input.program_id, surface_code = surface.surface_code, recognition = ?recognition, compatible = true, "native Solana decoder recognized contextual instruction"); return recognition; } - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { + fn decode( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderExecutionResult { let result = if input.program_id == kb_program_ids::SYSTEM_PROGRAM_ID { - crate::solana_core_system_decode(input) + crate::decoder_solana_core_system_decode(input) } else if input.program_id == kb_program_ids::COMPUTE_BUDGET_PROGRAM_ID { - crate::solana_core_compute_budget_decode(input) + crate::decoder_solana_core_compute_budget_decode(input) } else if input.program_id == kb_program_ids::ADDRESS_LOOKUP_TABLE_PROGRAM_ID { - crate::solana_core_address_lookup_table_decode(input) + crate::decoder_solana_core_address_lookup_table_decode(input) } else if input.program_id == kb_program_ids::CONFIG_PROGRAM_ID { - crate::solana_core_config_decode(input) + crate::decoder_solana_core_config_decode(input) } else if input.program_id == kb_program_ids::FEATURE_PROGRAM_ID { - crate::solana_core_feature_decode(input) + crate::decoder_solana_core_feature_decode(input) } else if input.program_id == kb_program_ids::VOTE_PROGRAM_ID { - crate::solana_core_vote_decode(input) + crate::decoder_solana_core_vote_decode(input) } else if input.program_id == kb_program_ids::STAKE_PROGRAM_ID { - crate::solana_core_stake_decode(input) + crate::decoder_solana_core_stake_decode(input) } else if input.program_id == kb_program_ids::SLASHING_PROGRAM_ID { - crate::solana_core_slashing_decode(input) + crate::decoder_solana_core_slashing_decode(input) } else if is_signature_precompile(input.program_id.as_str()) { - crate::solana_core_precompiles_decode(input) + crate::decoder_solana_core_precompiles_decode(input) } else if input.program_id == kb_program_ids::ZK_ELGAMAL_PROOF_PROGRAM_ID { - crate::solana_core_zk_elgamal_decode(input) + crate::decoder_solana_core_zk_elgamal_decode(input) } else if input.program_id == kb_program_ids::ZK_TOKEN_PROOF_PROGRAM_ID { - crate::solana_core_zk_token_proof_decode(input) + crate::decoder_solana_core_zk_token_proof_decode(input) } else if is_loader_program(input.program_id.as_str()) { - crate::solana_core_loaders_decode(input) + crate::decoder_solana_core_loaders_decode(input) } else { - crate::DecoderExecutionResult::unsupported(std::option::Option::Some( + crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::Some( "unclassified_native_instruction".to_string(), )) }; if matches!( result.status, - crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported + crate::DcApiDecoderOutcomeStatus::Failed + | crate::DcApiDecoderOutcomeStatus::Unsupported ) { tracing::error!( - target: crate::SOLANA_CORE_TRACING_TARGET, + target: crate::DC_SOLANA_CORE_TRACING_TARGET, action = "decode_failure", signature = %input.signature, slot = input.slot, @@ -301,7 +308,7 @@ impl crate::InstructionDecoder for crate::SolanaCoreDecoder { processor_version = env!("CARGO_PKG_VERSION"), input_key = %input.replay_input_key, payload_hash = ?input.instruction_payload_hash, - payload_length = ?crate::solana_core_decoded_payload_length(input), + payload_length = ?crate::decoder_solana_core_decoded_payload_length(input), transaction_failed = input.transaction_failed, transaction_error = ?input.transaction_err_json, result_status = ?result.status, @@ -310,7 +317,7 @@ impl crate::InstructionDecoder for crate::SolanaCoreDecoder { "native instruction was not decoded successfully" ); } - tracing::debug!(target: crate::SOLANA_CORE_TRACING_TARGET, action = "decode", signature = %input.signature, slot = input.slot, instruction_path = %input.instruction_path, program_id = %input.program_id, input_key = %input.replay_input_key, payload_hash = ?input.instruction_payload_hash, transaction_failed = input.transaction_failed, transaction_error = ?input.transaction_err_json, result_status = ?result.status, recognized_entry_code = ?result.recognized_entry_code, observation_count = result.observations.len(), diagnostic_count = result.diagnostics.len(), "native instruction decode completed"); + tracing::debug!(target: crate::DC_SOLANA_CORE_TRACING_TARGET, action = "decode", signature = %input.signature, slot = input.slot, instruction_path = %input.instruction_path, program_id = %input.program_id, input_key = %input.replay_input_key, payload_hash = ?input.instruction_payload_hash, transaction_failed = input.transaction_failed, transaction_error = ?input.transaction_err_json, result_status = ?result.status, recognized_entry_code = ?result.recognized_entry_code, observation_count = result.observations.len(), diagnostic_count = result.diagnostics.len(), "native instruction decode completed"); return result; } } @@ -337,8 +344,8 @@ fn is_historical_native_program(program_id: &str) -> bool { #[cfg(test)] mod tests { - fn replay_input(program_id: &str) -> crate::CoreInstructionReplayInput { - let result = crate::CoreInstructionReplayInput::new( + fn replay_input(program_id: &str) -> crate::MdCoreInstructionReplayInput { + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -363,9 +370,9 @@ mod tests { #[test] fn vote_program_is_dispatched_without_false_decode_for_unknown_tag() { - let decoder = crate::SolanaCoreDecoder; + let decoder = crate::DcSolanaCoreDecoder; let input = replay_input(kb_program_ids::VOTE_PROGRAM_ID); - let recognition = crate::InstructionDecoder::recognize(&decoder, &input); + let recognition = crate::DcApiInstructionDecoder::recognize(&decoder, &input); assert!(recognition.compatible); assert_eq!( recognition.surface_code.as_deref(), @@ -375,16 +382,16 @@ mod tests { recognition.entry_code.as_deref(), std::option::Option::Some("unknown_vote_instruction") ); - let result = crate::InstructionDecoder::decode(&decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported); + let result = crate::DcApiInstructionDecoder::decode(&decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported); assert!(result.observations.is_empty()); } #[test] fn stake_program_is_dispatched_without_false_decode_for_unknown_tag() { - let decoder = crate::SolanaCoreDecoder; + let decoder = crate::DcSolanaCoreDecoder; let input = replay_input(kb_program_ids::STAKE_PROGRAM_ID); - let recognition = crate::InstructionDecoder::recognize(&decoder, &input); + let recognition = crate::DcApiInstructionDecoder::recognize(&decoder, &input); assert!(recognition.compatible); assert_eq!( recognition.surface_code.as_deref(), @@ -394,16 +401,16 @@ mod tests { recognition.entry_code.as_deref(), std::option::Option::Some("unknown_stake_instruction") ); - let result = crate::InstructionDecoder::decode(&decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported); + let result = crate::DcApiInstructionDecoder::decode(&decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported); assert!(result.observations.is_empty()); } #[test] fn zk_token_proof_program_dispatches_to_current_noop_fallback() { - let decoder = crate::SolanaCoreDecoder; + let decoder = crate::DcSolanaCoreDecoder; let input = replay_input(kb_program_ids::ZK_TOKEN_PROOF_PROGRAM_ID); - let recognition = crate::InstructionDecoder::recognize(&decoder, &input); + let recognition = crate::DcApiInstructionDecoder::recognize(&decoder, &input); assert!(recognition.compatible); assert_eq!( recognition.surface_code.as_deref(), @@ -413,8 +420,8 @@ mod tests { recognition.entry_code.as_deref(), std::option::Option::Some("current_runtime_noop_invocation") ); - let result = crate::InstructionDecoder::decode(&decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode(&decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("current_runtime_noop_invocation") @@ -424,8 +431,8 @@ mod tests { #[test] fn every_native_registry_program_has_one_surface() { - let decoder = crate::SolanaCoreDecoder; - let surfaces = crate::InstructionDecoder::surfaces(&decoder); + let decoder = crate::DcSolanaCoreDecoder; + let surfaces = crate::DcApiInstructionDecoder::surfaces(&decoder); assert_eq!(surfaces.len(), kb_program_ids::native_program_ids().len()); for entry in kb_program_ids::native_program_ids() { assert!(surfaces.iter().any(|surface| return surface.program_id == entry.program_id())); @@ -434,9 +441,9 @@ mod tests { #[test] fn every_native_surface_has_declared_coverage_without_fallback_entries() { - let decoder = crate::SolanaCoreDecoder; - let surfaces = crate::InstructionDecoder::surfaces(&decoder); - let coverage = crate::InstructionDecoder::coverage(&decoder); + let decoder = crate::DcSolanaCoreDecoder; + let surfaces = crate::DcApiInstructionDecoder::surfaces(&decoder); + let coverage = crate::DcApiInstructionDecoder::coverage(&decoder); for surface in surfaces { assert!(coverage.iter().any(|entry| { return entry.program_id == surface.program_id @@ -451,9 +458,9 @@ mod tests { #[test] fn coverage_entries_are_unique_and_reference_declared_surfaces() { - let decoder = crate::SolanaCoreDecoder; - let surfaces = crate::InstructionDecoder::surfaces(&decoder); - let coverage = crate::InstructionDecoder::coverage(&decoder); + let decoder = crate::DcSolanaCoreDecoder; + let surfaces = crate::DcApiInstructionDecoder::surfaces(&decoder); + let coverage = crate::DcApiInstructionDecoder::coverage(&decoder); let mut identities = std::collections::BTreeSet::new(); for entry in coverage { let surface_code = match entry.surface_code.as_deref() { @@ -473,9 +480,9 @@ mod tests { #[test] fn slashing_program_is_dispatched_to_exact_decoder() { - let decoder = crate::SolanaCoreDecoder; + let decoder = crate::DcSolanaCoreDecoder; let input = replay_input(kb_program_ids::SLASHING_PROGRAM_ID); - let recognition = crate::InstructionDecoder::recognize(&decoder, &input); + let recognition = crate::DcApiInstructionDecoder::recognize(&decoder, &input); assert!(recognition.compatible); assert_eq!( recognition.surface_code.as_deref(), @@ -489,13 +496,13 @@ mod tests { #[test] fn deprecated_stake_config_account_is_not_an_instruction_surface() { - let decoder = crate::SolanaCoreDecoder; - let surfaces = crate::InstructionDecoder::surfaces(&decoder); + let decoder = crate::DcSolanaCoreDecoder; + let surfaces = crate::DcApiInstructionDecoder::surfaces(&decoder); assert!(!surfaces.iter().any(|surface| { return surface.program_id == kb_program_ids::STAKE_CONFIG_ACCOUNT_ID; })); let input = replay_input(kb_program_ids::STAKE_CONFIG_ACCOUNT_ID); - let recognition = crate::InstructionDecoder::recognize(&decoder, &input); + let recognition = crate::DcApiInstructionDecoder::recognize(&decoder, &input); assert!(!recognition.compatible); } @@ -517,8 +524,8 @@ mod tests { parsed.get("surface_count").and_then(serde_json::Value::as_u64); assert_eq!(declared_surface_count, std::option::Option::Some(18)); - let decoder = crate::SolanaCoreDecoder; - let compiled_surfaces = crate::InstructionDecoder::surfaces(&decoder); + let decoder = crate::DcSolanaCoreDecoder; + let compiled_surfaces = crate::DcApiInstructionDecoder::surfaces(&decoder); let compiled_surface_map = compiled_surfaces .iter() .map(|surface| { @@ -533,7 +540,7 @@ mod tests { .collect::>(); assert_eq!(native_registry.len(), 18); - let coverage = crate::InstructionDecoder::coverage(&decoder); + let coverage = crate::DcApiInstructionDecoder::coverage(&decoder); let mut compiled_coverage_counts = std::collections::BTreeMap::new(); for entry in &coverage { let count = compiled_coverage_counts.entry(entry.program_id.clone()).or_insert(0_usize); @@ -597,9 +604,9 @@ mod tests { #[test] fn unrelated_program_is_not_dispatched() { - let decoder = crate::SolanaCoreDecoder; + let decoder = crate::DcSolanaCoreDecoder; let input = replay_input(kb_program_ids::SPL_TOKEN_PROGRAM_ID); - let recognition = crate::InstructionDecoder::recognize(&decoder, &input); + let recognition = crate::DcApiInstructionDecoder::recognize(&decoder, &input); assert!(!recognition.compatible); } } diff --git a/kb-lib/src/decoder/solana/core/event.rs b/kb-lib/src/decoder/solana/core/event.rs index cb8ae8d..9363fac 100644 --- a/kb-lib/src/decoder/solana/core/event.rs +++ b/kb-lib/src/decoder/solana/core/event.rs @@ -4,39 +4,39 @@ //! Stable native event and decoder result builders. /// Builds one exact decoded native observation. -pub(crate) fn decoded_result( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_decoded_result( + input: &crate::MdCoreInstructionReplayInput, surface_code: &str, entry_code: &str, - event_family: crate::EventFamily, + event_family: crate::MdEventFamily, historical: bool, accounts: serde_json::Value, parameters: serde_json::Value, source_evidence: &str, -) -> crate::DecoderExecutionResult { - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(input.instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode(crate::SOLANA_CORE_PROTOCOL_CODE.to_string()), - surface_code: crate::SurfaceCode(surface_code.to_string()), - event_code: crate::EventCode(format!("{surface_code}.{entry_code}")), - event_name: crate::EventName(entry_code.to_string()), +) -> crate::DcApiDecoderExecutionResult { + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(input.instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode(crate::DC_SOLANA_CORE_PROTOCOL_CODE.to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")), + event_name: crate::MdEventName(entry_code.to_string()), event_family, source_kind: if input.instruction_path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction }, - confidence: crate::DecoderConfidence::ManualExact, + confidence: crate::MdDecoderConfidence::ManualExact, }; - let payload_hash = crate::solana_core_payload_hash(input); - let observation = crate::DecodedObservation { + let payload_hash = crate::decoder_solana_core_payload_hash(input); + let observation = crate::DcApiDecodedObservation { event_key: format!("{entry_code}:0"), event, payload_json: serde_json::json!({ - "eventVersion": crate::SOLANA_CORE_NATIVE_EVENT_VERSION, + "eventVersion": crate::DC_SOLANA_CORE_NATIVE_EVENT_VERSION, "programId": input.program_id, "surfaceCode": surface_code, "entryCode": entry_code, @@ -50,14 +50,14 @@ pub(crate) fn decoded_result( transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: !input.transaction_failed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: vec![source_evidence.to_string(), format!("payload_sha256:{payload_hash}")], }, }; - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some(entry_code.to_string()), observations: vec![observation], diagnostics: std::vec::Vec::new(), @@ -65,16 +65,16 @@ pub(crate) fn decoded_result( } /// Builds one failed native decode result. -pub(crate) fn failed_result( +pub(crate) fn decoder_solana_core_failed_result( entry_code: std::option::Option<&str>, code: &str, message: impl std::convert::Into, -) -> crate::DecoderExecutionResult { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, +) -> crate::DcApiDecoderExecutionResult { + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: entry_code.map(str::to_string), observations: std::vec::Vec::new(), - diagnostics: vec![crate::DecoderDiagnostic { + diagnostics: vec![crate::DcApiDecoderDiagnostic { code: code.to_string(), message: message.into(), retriable: false, @@ -83,16 +83,16 @@ pub(crate) fn failed_result( } /// Builds one unsupported native decode result with a bounded diagnostic. -pub(crate) fn unsupported_result( +pub(crate) fn decoder_solana_core_unsupported_result( entry_code: &str, code: &str, message: impl std::convert::Into, -) -> crate::DecoderExecutionResult { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Unsupported, +) -> crate::DcApiDecoderExecutionResult { + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Unsupported, recognized_entry_code: std::option::Option::Some(entry_code.to_string()), observations: std::vec::Vec::new(), - diagnostics: vec![crate::DecoderDiagnostic { + diagnostics: vec![crate::DcApiDecoderDiagnostic { code: code.to_string(), message: message.into(), retriable: false, diff --git a/kb-lib/src/decoder/solana/core/feature.rs b/kb-lib/src/decoder/solana/core/feature.rs index 2657a34..d0bde64 100644 --- a/kb-lib/src/decoder/solana/core/feature.rs +++ b/kb-lib/src/decoder/solana/core/feature.rs @@ -4,20 +4,21 @@ //! Exact Feature Gate instruction decoding from the official interface contract. const SOURCE: &str = "solana-feature-gate-interface@4.0.0 revoke_pending_activation contract"; -const REVOKE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("feature_account", true, true), - crate::SolanaCoreAccountRole::new("incinerator", true, false), - crate::SolanaCoreAccountRole::new("system_program", false, false), +const REVOKE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("feature_account", true, true), + crate::DcSolanaCoreAccountRole::new("incinerator", true, false), + crate::DcSolanaCoreAccountRole::new("system_program", false, false), ]; /// Returns declared Feature Gate instruction coverage. -pub(crate) fn feature_coverage() -> std::vec::Vec { - return vec![crate::DecoderCoverageDeclaration { +pub(crate) fn decoder_solana_core_feature_coverage() +-> std::vec::Vec { + return vec![crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::FEATURE_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_FEATURE_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_FEATURE_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: "revoke_pending_activation".to_string(), discriminator_hex: std::option::Option::Some("00".to_string()), historical: false, @@ -25,18 +26,18 @@ pub(crate) fn feature_coverage() -> std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_FEATURE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_FEATURE_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_feature_instruction".to_string()), std::option::Option::None, ); @@ -47,24 +48,24 @@ pub(crate) fn feature_recognize( std::option::Option::Some(_value) => "unknown_feature_instruction", std::option::Option::None => "malformed_feature_instruction", }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( bytes.as_slice() == [0], priority, - std::option::Option::Some(crate::SOLANA_CORE_FEATURE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_FEATURE_SURFACE_CODE.to_string()), std::option::Option::Some(entry_code.to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(1)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(1)), ); } /// Decodes one Feature Gate instruction. -pub(crate) fn feature_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_feature_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_feature_instruction"), "feature_payload_invalid", error.to_string(), @@ -72,25 +73,25 @@ pub(crate) fn feature_decode( }, }; if bytes.is_empty() { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_feature_instruction"), "feature_payload_empty", "Feature Gate instruction payload is empty", ); } if bytes[0] != 0 { - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_feature_instruction", "feature_tag_unknown", format!( "unknown Feature Gate instruction tag {}; payload_sha256={}", bytes[0], - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); } if bytes.len() != 1 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("revoke_pending_activation"), "feature_instruction_size_invalid", format!( @@ -99,12 +100,16 @@ pub(crate) fn feature_decode( ), ); } - let accounts_result = - crate::solana_core_resolve_accounts(input, REVOKE_ROLES, 3, std::option::Option::Some(3)); + let accounts_result = crate::decoder_solana_core_resolve_accounts( + input, + REVOKE_ROLES, + 3, + std::option::Option::Some(3), + ); let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("revoke_pending_activation"), "feature_accounts_invalid", error.to_string(), @@ -113,17 +118,17 @@ pub(crate) fn feature_decode( }; let fixed_accounts_result = validate_fixed_accounts(&accounts); if let std::result::Result::Err(error) = fixed_accounts_result { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("revoke_pending_activation"), "feature_fixed_account_invalid", error.to_string(), ); } - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_FEATURE_SURFACE_CODE, + crate::DC_SOLANA_CORE_FEATURE_SURFACE_CODE, "revoke_pending_activation", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, accounts, serde_json::json!({ @@ -164,7 +169,7 @@ fn validate_fixed_accounts(accounts: &serde_json::Value) -> kb_core::Result<()> mod tests { use base64::Engine; // rust-rules: trait-import - fn replay_input(bytes: &[u8], transaction_failed: bool) -> crate::CoreInstructionReplayInput { + fn replay_input(bytes: &[u8], transaction_failed: bool) -> crate::MdCoreInstructionReplayInput { let keys = [ "FeatureAccount11111111111111111111111111111", kb_program_ids::INCINERATOR_PROGRAM_ID, @@ -191,7 +196,7 @@ mod tests { return serde_json::json!({"accountIndex": index, "accountKey": key}); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -223,22 +228,22 @@ mod tests { #[test] fn official_payload_is_recognized_exactly() { let input = replay_input(&[0], false); - let recognition = crate::solana_core_feature_recognize(&input, 100); + let recognition = crate::decoder_solana_core_feature_recognize(&input, 100); assert!(recognition.compatible); assert!(recognition.exact); assert_eq!( recognition.entry_code.as_deref(), std::option::Option::Some("revoke_pending_activation") ); - let unknown = crate::solana_core_feature_recognize(&replay_input(&[7], false), 100); + let unknown = crate::decoder_solana_core_feature_recognize(&replay_input(&[7], false), 100); assert!(unknown.compatible); assert!(!unknown.exact); } #[test] fn revoke_pending_activation_decodes_exact_official_layout() { - let result = crate::solana_core_feature_decode(&replay_input(&[0], false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_feature_decode(&replay_input(&[0], false)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("revoke_pending_activation") @@ -248,29 +253,29 @@ mod tests { #[test] fn unknown_truncated_trailing_and_wrong_fixed_accounts_are_safe() { - let empty = crate::solana_core_feature_decode(&replay_input(&[], false)); - assert_eq!(empty.status, crate::DecoderOutcomeStatus::Failed); - let unknown = crate::solana_core_feature_decode(&replay_input(&[7], false)); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); - let trailing = crate::solana_core_feature_decode(&replay_input(&[0, 1], false)); - assert_eq!(trailing.status, crate::DecoderOutcomeStatus::Failed); + let empty = crate::decoder_solana_core_feature_decode(&replay_input(&[], false)); + assert_eq!(empty.status, crate::DcApiDecoderOutcomeStatus::Failed); + let unknown = crate::decoder_solana_core_feature_decode(&replay_input(&[7], false)); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); + let trailing = crate::decoder_solana_core_feature_decode(&replay_input(&[0, 1], false)); + assert_eq!(trailing.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut wrong = replay_input(&[0], false); wrong.instruction_accounts_json[1]["accountKey"] = serde_json::json!("wrong"); wrong.account_keys_json[1]["accountKey"] = serde_json::json!("wrong"); - let invalid = crate::solana_core_feature_decode(&wrong); - assert_eq!(invalid.status, crate::DecoderOutcomeStatus::Failed); + let invalid = crate::decoder_solana_core_feature_decode(&wrong); + assert_eq!(invalid.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn failed_feature_revoke_is_uncommitted() { - let result = crate::solana_core_feature_decode(&replay_input(&[0], true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_feature_decode(&replay_input(&[0], true)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); } #[test] fn coverage_declares_the_single_official_instruction() { - let coverage = crate::solana_core_feature_coverage(); + let coverage = crate::decoder_solana_core_feature_coverage(); assert_eq!(coverage.len(), 1); assert_eq!(coverage[0].entry_code, "revoke_pending_activation"); assert_eq!(coverage[0].discriminator_hex.as_deref(), std::option::Option::Some("00")); diff --git a/kb-lib/src/decoder/solana/core/loaders.rs b/kb-lib/src/decoder/solana/core/loaders.rs index deb9121..86c25b7 100644 --- a/kb-lib/src/decoder/solana/core/loaders.rs +++ b/kb-lib/src/decoder/solana/core/loaders.rs @@ -8,101 +8,102 @@ const SOURCE_BPF_LOADER_V3: &str = "solana-loader-v3-interface@8.0.1"; const SOURCE_LOADER_V4: &str = "solana-loader-v4-interface@3.1.0"; const SOURCE_NATIVE_LOADER: &str = "Agave native_loader runtime dispatch"; -const IMMUTABLE_WRITE_ROLES: &[crate::SolanaCoreAccountRole] = - &[crate::SolanaCoreAccountRole::new("program_account", true, true)]; -const IMMUTABLE_FINALIZE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, true), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), +const IMMUTABLE_WRITE_ROLES: &[crate::DcSolanaCoreAccountRole] = + &[crate::DcSolanaCoreAccountRole::new("program_account", true, true)]; +const IMMUTABLE_FINALIZE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, true), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), ]; -const UPGRADEABLE_INITIALIZE_BUFFER_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("buffer_account", true, false), - crate::SolanaCoreAccountRole::new("buffer_authority", false, false), +const UPGRADEABLE_INITIALIZE_BUFFER_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("buffer_account", true, false), + crate::DcSolanaCoreAccountRole::new("buffer_authority", false, false), ]; -const UPGRADEABLE_WRITE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("buffer_account", true, false), - crate::SolanaCoreAccountRole::new("buffer_authority", false, true), +const UPGRADEABLE_WRITE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("buffer_account", true, false), + crate::DcSolanaCoreAccountRole::new("buffer_authority", false, true), ]; -const UPGRADEABLE_DEPLOY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("payer", true, true), - crate::SolanaCoreAccountRole::new("programdata_account", true, false), - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("buffer_account", true, false), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("system_program", false, false), - crate::SolanaCoreAccountRole::new("upgrade_authority", false, true), +const UPGRADEABLE_DEPLOY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("payer", true, true), + crate::DcSolanaCoreAccountRole::new("programdata_account", true, false), + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("buffer_account", true, false), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("system_program", false, false), + crate::DcSolanaCoreAccountRole::new("upgrade_authority", false, true), ]; -const UPGRADEABLE_UPGRADE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("programdata_account", true, false), - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("buffer_account", true, false), - crate::SolanaCoreAccountRole::new("spill_account", true, false), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("upgrade_authority", false, true), +const UPGRADEABLE_UPGRADE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("programdata_account", true, false), + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("buffer_account", true, false), + crate::DcSolanaCoreAccountRole::new("spill_account", true, false), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("upgrade_authority", false, true), ]; -const UPGRADEABLE_SET_AUTHORITY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("authority_target", true, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, false), +const UPGRADEABLE_SET_AUTHORITY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("authority_target", true, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, false), ]; -const UPGRADEABLE_CLOSE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("close_target", true, false), - crate::SolanaCoreAccountRole::new("recipient", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), - crate::SolanaCoreAccountRole::new("associated_program", true, false), +const UPGRADEABLE_CLOSE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("close_target", true, false), + crate::DcSolanaCoreAccountRole::new("recipient", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), + crate::DcSolanaCoreAccountRole::new("associated_program", true, false), ]; -const UPGRADEABLE_EXTEND_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("programdata_account", true, false), - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("system_program", false, false), - crate::SolanaCoreAccountRole::new("payer", true, true), +const UPGRADEABLE_EXTEND_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("programdata_account", true, false), + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("system_program", false, false), + crate::DcSolanaCoreAccountRole::new("payer", true, true), ]; -const UPGRADEABLE_SET_AUTHORITY_CHECKED_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("authority_target", true, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, true), +const UPGRADEABLE_SET_AUTHORITY_CHECKED_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("authority_target", true, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), ]; -const LOADER_V4_WRITE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), +const LOADER_V4_WRITE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), ]; -const LOADER_V4_COPY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), - crate::SolanaCoreAccountRole::new("source_program_account", false, false), +const LOADER_V4_COPY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), + crate::DcSolanaCoreAccountRole::new("source_program_account", false, false), ]; -const LOADER_V4_SET_LENGTH_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), - crate::SolanaCoreAccountRole::new("recipient", true, false), +const LOADER_V4_SET_LENGTH_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), + crate::DcSolanaCoreAccountRole::new("recipient", true, false), ]; -const LOADER_V4_DEPLOY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), - crate::SolanaCoreAccountRole::new("source_program_account", true, false), +const LOADER_V4_DEPLOY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), + crate::DcSolanaCoreAccountRole::new("source_program_account", true, false), ]; -const LOADER_V4_AUTHORITY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), +const LOADER_V4_AUTHORITY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), ]; -const LOADER_V4_TRANSFER_AUTHORITY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, true), +const LOADER_V4_TRANSFER_AUTHORITY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), ]; -const LOADER_V4_FINALIZE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("program_account", true, false), - crate::SolanaCoreAccountRole::new("authority", false, true), - crate::SolanaCoreAccountRole::new("next_version_program", false, false), +const LOADER_V4_FINALIZE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("program_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority", false, true), + crate::DcSolanaCoreAccountRole::new("next_version_program", false, false), ]; /// Returns declared loader instruction coverage. -pub(crate) fn loaders_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_loaders_coverage() +-> std::vec::Vec { let mut output = std::vec::Vec::new(); output.push(coverage_entry( kb_program_ids::NATIVE_LOADER_PROGRAM_ID, - crate::SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE, + crate::DC_SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE, "direct_invocation_opaque", std::option::Option::None, true, @@ -110,12 +111,12 @@ pub(crate) fn loaders_coverage() -> std::vec::Vec std::vec::Vec std::vec::Vec std::vec::Vec crate::DecoderRecognition { +) -> crate::DcApiDecoderRecognition { let surface_code = match surface_code(input.program_id.as_str()) { std::option::Option::Some(value) => value, - std::option::Option::None => return crate::DecoderRecognition::incompatible(), + std::option::Option::None => return crate::DcApiDecoderRecognition::incompatible(), }; if input.program_id == kb_program_ids::NATIVE_LOADER_PROGRAM_ID { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( true, priority, std::option::Option::Some(surface_code.to_string()), @@ -190,11 +191,11 @@ pub(crate) fn loaders_recognize( std::option::Option::None, ); } - let bytes_result = crate::solana_core_decode_instruction_data(input); + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some(surface_code.to_string()), @@ -204,32 +205,32 @@ pub(crate) fn loaders_recognize( }, }; let entry_code = entry_code(input.program_id.as_str(), bytes.as_slice()); - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( entry_code.is_some(), priority, std::option::Option::Some(surface_code.to_string()), entry_code.map(str::to_string).or_else(|| { return std::option::Option::Some("unknown_loader_instruction".to_string()); }), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), 4), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), 4), ); } /// Decodes one loader instruction. -pub(crate) fn loaders_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { +pub(crate) fn decoder_solana_core_loaders_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { if input.program_id == kb_program_ids::NATIVE_LOADER_PROGRAM_ID { - tracing::debug!(target: crate::SOLANA_CORE_TRACING_TARGET, action = "decode_native_loader", signature = %input.signature, instruction_path = %input.instruction_path, source = SOURCE_NATIVE_LOADER, "ignore opaque direct Native Loader invocation without inventing an instruction schema"); - return crate::DecoderExecutionResult::ignored(std::option::Option::Some( + tracing::debug!(target: crate::DC_SOLANA_CORE_TRACING_TARGET, action = "decode_native_loader", signature = %input.signature, instruction_path = %input.instruction_path, source = SOURCE_NATIVE_LOADER, "ignore opaque direct Native Loader invocation without inventing an instruction schema"); + return crate::DcApiDecoderExecutionResult::ignored(std::option::Option::Some( "direct_invocation_opaque".to_string(), )); } - let bytes_result = crate::solana_core_decode_instruction_data(input); + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_loader_instruction"), "loader_payload_invalid", error.to_string(), @@ -247,7 +248,7 @@ pub(crate) fn loaders_decode( if input.program_id == kb_program_ids::LOADER_V4_PROGRAM_ID { return decode_v4(input, bytes.as_slice()); } - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_loader_instruction", "loader_program_unknown", format!("unsupported loader program id {}", input.program_id), @@ -255,17 +256,17 @@ pub(crate) fn loaders_decode( } fn decode_immutable( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let tag = match read_tag(bytes, "immutable_loader_tag_truncated") { std::result::Result::Ok(value) => value, std::result::Result::Err(result) => return result, }; let surface_code = if input.program_id == kb_program_ids::BPF_LOADER_DEPRECATED_PROGRAM_ID { - crate::SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE + crate::DC_SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE } else { - crate::SOLANA_CORE_BPF_LOADER_SURFACE_CODE + crate::DC_SOLANA_CORE_BPF_LOADER_SURFACE_CODE }; return match tag { 0 => decode_immutable_write(input, bytes, surface_code), @@ -277,7 +278,7 @@ fn decode_immutable( input, surface_code, "finalize", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, true, IMMUTABLE_FINALIZE_ROLES, 2, @@ -290,12 +291,12 @@ fn decode_immutable( } fn decode_immutable_write( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], surface_code: &str, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() < 12 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("write"), "loader_write_truncated", format!( @@ -304,10 +305,10 @@ fn decode_immutable_write( ), ); } - let offset = match crate::solana_core_read_u32_le(bytes, 4) { + let offset = match crate::decoder_solana_core_read_u32_le(bytes, 4) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("write"), "loader_write_offset_truncated", error.to_string(), @@ -326,15 +327,15 @@ fn decode_immutable_write( input, surface_code, "write", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, true, IMMUTABLE_WRITE_ROLES, 1, serde_json::json!({ "offset": offset, "byteLength": byte_length, - "bytesSha256": crate::solana_core_hash_bytes(written_bytes), - "bytesPrefixHex": crate::solana_core_hexadecimal_prefix( + "bytesSha256": crate::decoder_solana_core_hash_bytes(written_bytes), + "bytesPrefixHex": crate::decoder_solana_core_hexadecimal_prefix( written_bytes, written_bytes.len().min(16), ), @@ -344,9 +345,9 @@ fn decode_immutable_write( } fn decode_upgradeable( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let tag = match read_tag(bytes, "upgradeable_loader_tag_truncated") { std::result::Result::Ok(value) => value, std::result::Result::Err(result) => return result, @@ -370,7 +371,7 @@ fn decode_upgradeable( { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "upgradeable_loader_wincode_invalid", format!("cannot decode exact Loader v3 {entry_code}: {error}"), @@ -381,9 +382,9 @@ fn decode_upgradeable( solana_loader_v3_interface::instruction::UpgradeableLoaderInstruction::InitializeBuffer => { build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "initialize_buffer", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, UPGRADEABLE_INITIALIZE_BUFFER_ROLES, 1, @@ -396,17 +397,17 @@ fn decode_upgradeable( bytes: written_bytes, } => build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "write", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, UPGRADEABLE_WRITE_ROLES, 2, serde_json::json!({ "offset": offset, "byteLength": written_bytes.len(), - "bytesSha256": crate::solana_core_hash_bytes(written_bytes.as_slice()), - "bytesPrefixHex": crate::solana_core_hexadecimal_prefix( + "bytesSha256": crate::decoder_solana_core_hash_bytes(written_bytes.as_slice()), + "bytesPrefixHex": crate::decoder_solana_core_hexadecimal_prefix( written_bytes.as_slice(), written_bytes.len().min(16), ), @@ -418,9 +419,9 @@ fn decode_upgradeable( close_buffer, } => build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "deploy_with_max_data_len", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, bytes.len() == 12, UPGRADEABLE_DEPLOY_ROLES, 8, @@ -435,9 +436,9 @@ fn decode_upgradeable( close_buffer, } => build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "upgrade", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, bytes.len() == 4, UPGRADEABLE_UPGRADE_ROLES, 7, @@ -450,9 +451,9 @@ fn decode_upgradeable( solana_loader_v3_interface::instruction::UpgradeableLoaderInstruction::SetAuthority => { build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "set_authority", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, UPGRADEABLE_SET_AUTHORITY_ROLES, 2, @@ -464,9 +465,9 @@ fn decode_upgradeable( tombstone, } => build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "close", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, bytes.len() == 4, UPGRADEABLE_CLOSE_ROLES, 2, @@ -481,7 +482,7 @@ fn decode_upgradeable( } => { let account_count = account_count(input); if account_count == 3 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("extend_program"), "upgradeable_loader_extend_accounts_invalid", "extend_program requires either two accounts or the complete optional system/payer pair", @@ -489,9 +490,9 @@ fn decode_upgradeable( } build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "extend_program", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, UPGRADEABLE_EXTEND_ROLES, 2, @@ -505,9 +506,9 @@ fn decode_upgradeable( solana_loader_v3_interface::instruction::UpgradeableLoaderInstruction::SetAuthorityChecked => { build( input, - crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, + crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE, "set_authority_checked", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, UPGRADEABLE_SET_AUTHORITY_CHECKED_ROLES, 3, @@ -519,9 +520,9 @@ fn decode_upgradeable( } fn decode_v4( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let tag = match read_tag(bytes, "loader_v4_tag_truncated") { std::result::Result::Ok(value) => value, std::result::Result::Err(result) => return result, @@ -530,7 +531,7 @@ fn decode_v4( 0 => decode_write( input, bytes, - crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE, + crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE, false, LOADER_V4_WRITE_ROLES, 2, @@ -541,9 +542,9 @@ fn decode_v4( 3 => decode_unit( input, bytes, - crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE, + crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE, "deploy", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, LOADER_V4_DEPLOY_ROLES, 2, SOURCE_LOADER_V4, @@ -551,9 +552,9 @@ fn decode_v4( 4 => decode_unit( input, bytes, - crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE, + crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE, "retract", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, LOADER_V4_AUTHORITY_ROLES, 2, SOURCE_LOADER_V4, @@ -561,9 +562,9 @@ fn decode_v4( 5 => decode_unit( input, bytes, - crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE, + crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE, "transfer_authority", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, LOADER_V4_TRANSFER_AUTHORITY_ROLES, 3, SOURCE_LOADER_V4, @@ -571,9 +572,9 @@ fn decode_v4( 6 => decode_unit( input, bytes, - crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE, + crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE, "finalize", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, LOADER_V4_FINALIZE_ROLES, 3, SOURCE_LOADER_V4, @@ -583,25 +584,25 @@ fn decode_v4( } fn decode_write( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], surface_code: &str, historical: bool, - roles: &[crate::SolanaCoreAccountRole], + roles: &[crate::DcSolanaCoreAccountRole], minimum_count: usize, source: &str, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() < 16 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("write"), "loader_write_truncated", format!("loader write requires at least 16 bytes but received {}", bytes.len()), ); } - let offset = match crate::solana_core_read_u32_le(bytes, 4) { + let offset = match crate::decoder_solana_core_read_u32_le(bytes, 4) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("write"), "loader_write_offset_truncated", error.to_string(), @@ -620,15 +621,15 @@ fn decode_write( input, surface_code, "write", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, historical, roles, minimum_count, serde_json::json!({ "offset": offset, "byteLength": byte_length, - "bytesSha256": crate::solana_core_hash_bytes(written_bytes), - "bytesPrefixHex": crate::solana_core_hexadecimal_prefix( + "bytesSha256": crate::decoder_solana_core_hash_bytes(written_bytes), + "bytesPrefixHex": crate::decoder_solana_core_hexadecimal_prefix( written_bytes, written_bytes.len().min(16), ), @@ -638,36 +639,36 @@ fn decode_write( } fn decode_copy( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() != 16 { return size_failure("copy", 16, bytes.len()); } - let destination_offset = match crate::solana_core_read_u32_le(bytes, 4) { + let destination_offset = match crate::decoder_solana_core_read_u32_le(bytes, 4) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("copy"), "loader_v4_copy_truncated", error.to_string(), ); }, }; - let source_offset = match crate::solana_core_read_u32_le(bytes, 8) { + let source_offset = match crate::decoder_solana_core_read_u32_le(bytes, 8) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("copy"), "loader_v4_copy_truncated", error.to_string(), ); }, }; - let length = match crate::solana_core_read_u32_le(bytes, 12) { + let length = match crate::decoder_solana_core_read_u32_le(bytes, 12) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("copy"), "loader_v4_copy_truncated", error.to_string(), @@ -676,9 +677,9 @@ fn decode_copy( }; return build( input, - crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE, + crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE, "copy", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, LOADER_V4_COPY_ROLES, 3, @@ -692,16 +693,16 @@ fn decode_copy( } fn decode_set_program_length( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() != 8 { return size_failure("set_program_length", 8, bytes.len()); } - let new_size = match crate::solana_core_read_u32_le(bytes, 4) { + let new_size = match crate::decoder_solana_core_read_u32_le(bytes, 4) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("set_program_length"), "loader_v4_set_length_truncated", error.to_string(), @@ -710,9 +711,9 @@ fn decode_set_program_length( }; return build( input, - crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE, + crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE, "set_program_length", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, LOADER_V4_SET_LENGTH_ROLES, 2, @@ -725,15 +726,15 @@ fn decode_set_program_length( } fn decode_unit( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], surface_code: &str, entry_code: &str, - family: crate::EventFamily, - roles: &[crate::SolanaCoreAccountRole], + family: crate::MdEventFamily, + roles: &[crate::DcSolanaCoreAccountRole], minimum_count: usize, source: &str, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() != 4 { return size_failure(entry_code, 4, bytes.len()); } @@ -751,29 +752,33 @@ fn decode_unit( } fn build( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, surface_code: &str, entry_code: &str, - family: crate::EventFamily, + family: crate::MdEventFamily, historical: bool, - roles: &[crate::SolanaCoreAccountRole], + roles: &[crate::DcSolanaCoreAccountRole], minimum_count: usize, parameters: serde_json::Value, source: &str, -) -> crate::DecoderExecutionResult { - let accounts_result = - crate::solana_core_resolve_accounts(input, roles, minimum_count, std::option::Option::None); +) -> crate::DcApiDecoderExecutionResult { + let accounts_result = crate::decoder_solana_core_resolve_accounts( + input, + roles, + minimum_count, + std::option::Option::None, + ); let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "loader_accounts_invalid", error.to_string(), ); }, }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, surface_code, entry_code, @@ -785,12 +790,15 @@ fn build( ); } -fn read_tag(bytes: &[u8], code: &str) -> std::result::Result { - let result = crate::solana_core_read_u32_le(bytes, 0); +fn read_tag( + bytes: &[u8], + code: &str, +) -> std::result::Result { + let result = crate::decoder_solana_core_read_u32_le(bytes, 0); return match result { std::result::Result::Ok(value) => std::result::Result::Ok(value), std::result::Result::Err(error) => { - std::result::Result::Err(crate::solana_core_failed_result( + std::result::Result::Err(crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_loader_instruction"), code, error.to_string(), @@ -804,11 +812,11 @@ fn exact_u32_vector_length( length_offset: usize, data_offset: usize, entry_code: &str, -) -> std::result::Result { - let encoded_length = match crate::solana_core_read_u32_le(bytes, length_offset) { +) -> std::result::Result { + let encoded_length = match crate::decoder_solana_core_read_u32_le(bytes, length_offset) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return std::result::Result::Err(crate::solana_core_failed_result( + return std::result::Result::Err(crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "loader_vector_length_truncated", error.to_string(), @@ -818,7 +826,7 @@ fn exact_u32_vector_length( let expected_length = encoded_length as usize; let actual_length = bytes.len().saturating_sub(data_offset); if bytes.len() < data_offset || actual_length != expected_length { - return std::result::Result::Err(crate::solana_core_failed_result( + return std::result::Result::Err(crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "loader_vector_length_mismatch", format!( @@ -834,11 +842,11 @@ fn exact_vector_length( length_offset: usize, data_offset: usize, entry_code: &str, -) -> std::result::Result { - let encoded_length = match crate::solana_core_read_u64_le(bytes, length_offset) { +) -> std::result::Result { + let encoded_length = match crate::decoder_solana_core_read_u64_le(bytes, length_offset) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return std::result::Result::Err(crate::solana_core_failed_result( + return std::result::Result::Err(crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "loader_vector_length_truncated", error.to_string(), @@ -848,7 +856,7 @@ fn exact_vector_length( let expected_length = match usize::try_from(encoded_length) { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return std::result::Result::Err(crate::solana_core_failed_result( + return std::result::Result::Err(crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "loader_vector_length_overflow", format!("loader vector length {encoded_length} does not fit usize"), @@ -857,7 +865,7 @@ fn exact_vector_length( }; let actual_length = bytes.len().saturating_sub(data_offset); if bytes.len() < data_offset || actual_length != expected_length { - return std::result::Result::Err(crate::solana_core_failed_result( + return std::result::Result::Err(crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "loader_vector_length_mismatch", format!( @@ -868,8 +876,12 @@ fn exact_vector_length( return std::result::Result::Ok(expected_length); } -fn size_failure(entry_code: &str, expected: usize, actual: usize) -> crate::DecoderExecutionResult { - return crate::solana_core_failed_result( +fn size_failure( + entry_code: &str, + expected: usize, + actual: usize, +) -> crate::DcApiDecoderExecutionResult { + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "loader_instruction_size_invalid", format!("loader {entry_code} requires exactly {expected} bytes but received {actual}"), @@ -877,31 +889,31 @@ fn size_failure(entry_code: &str, expected: usize, actual: usize) -> crate::Deco } fn unknown_tag( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, entry_code: &str, tag: u32, -) -> crate::DecoderExecutionResult { - return crate::solana_core_unsupported_result( +) -> crate::DcApiDecoderExecutionResult { + return crate::decoder_solana_core_unsupported_result( entry_code, "loader_tag_unknown", format!( "unknown loader instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); } fn surface_code(program_id: &str) -> std::option::Option<&'static str> { return if program_id == kb_program_ids::BPF_LOADER_DEPRECATED_PROGRAM_ID { - std::option::Option::Some(crate::SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE) + std::option::Option::Some(crate::DC_SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE) } else if program_id == kb_program_ids::BPF_LOADER_PROGRAM_ID { - std::option::Option::Some(crate::SOLANA_CORE_BPF_LOADER_SURFACE_CODE) + std::option::Option::Some(crate::DC_SOLANA_CORE_BPF_LOADER_SURFACE_CODE) } else if program_id == kb_program_ids::BPF_LOADER_UPGRADEABLE_PROGRAM_ID { - std::option::Option::Some(crate::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE) + std::option::Option::Some(crate::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE) } else if program_id == kb_program_ids::LOADER_V4_PROGRAM_ID { - std::option::Option::Some(crate::SOLANA_CORE_LOADER_V4_SURFACE_CODE) + std::option::Option::Some(crate::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE) } else if program_id == kb_program_ids::NATIVE_LOADER_PROGRAM_ID { - std::option::Option::Some(crate::SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE) + std::option::Option::Some(crate::DC_SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE) } else { std::option::Option::None }; @@ -911,7 +923,7 @@ fn entry_code(program_id: &str, bytes: &[u8]) -> std::option::Option<&'static st if program_id == kb_program_ids::NATIVE_LOADER_PROGRAM_ID { return std::option::Option::Some("direct_invocation_opaque"); } - let tag = match crate::solana_core_read_u32_le(bytes, 0) { + let tag = match crate::decoder_solana_core_read_u32_le(bytes, 0) { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => return std::option::Option::None, }; @@ -952,7 +964,7 @@ fn entry_code(program_id: &str, bytes: &[u8]) -> std::option::Option<&'static st return std::option::Option::None; } -fn account_count(input: &crate::CoreInstructionReplayInput) -> usize { +fn account_count(input: &crate::MdCoreInstructionReplayInput) -> usize { return input.instruction_accounts_json.as_array().map(std::vec::Vec::len).unwrap_or(0); } @@ -962,11 +974,11 @@ fn coverage_entry( entry_code: &str, discriminator_hex: std::option::Option, historical: bool, -) -> crate::DecoderCoverageDeclaration { - return crate::DecoderCoverageDeclaration { +) -> crate::DcApiDecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: program_id.to_string(), surface_code: std::option::Option::Some(surface_code.to_string()), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: entry_code.to_string(), discriminator_hex, historical, @@ -987,7 +999,7 @@ mod tests { bytes: &[u8], account_count: usize, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let encoded = base64::engine::general_purpose::STANDARD.encode(bytes); let account_keys = (0..account_count) .map(|index| { @@ -1009,7 +1021,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -1060,9 +1072,9 @@ mod tests { program_id: &str, bytes: &[u8], account_count: usize, - ) -> crate::DecoderExecutionResult { + ) -> crate::DcApiDecoderExecutionResult { let input = replay_input(program_id, bytes, account_count, false); - return crate::solana_core_loaders_decode(&input); + return crate::decoder_solana_core_loaders_decode(&input); } fn upgradeable( @@ -1083,7 +1095,7 @@ mod tests { kb_program_ids::BPF_LOADER_PROGRAM_ID, ] { let write_result = decode(program_id, immutable_write(0, 7, &[1, 2, 3]).as_slice(), 1); - assert_eq!(write_result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(write_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(write_result.observations[0].payload_json["parameters"]["offset"], 7); assert_eq!(write_result.observations[0].payload_json["parameters"]["byteLength"], 3); assert_eq!( @@ -1092,7 +1104,7 @@ mod tests { ); assert!(write_result.observations[0].payload_json["parameters"].get("bytes").is_none()); let finalize_result = decode(program_id, unit(1).as_slice(), 2); - assert_eq!(finalize_result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(finalize_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); } } @@ -1103,7 +1115,7 @@ mod tests { bytes.extend_from_slice(&800_u32.to_le_bytes()); bytes.extend_from_slice(vec![0x5a_u8; 800].as_slice()); let result = decode(kb_program_ids::BPF_LOADER_PROGRAM_ID, bytes.as_slice(), 1); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations[0].payload_json["parameters"]["offset"], 13_600); assert_eq!(result.observations[0].payload_json["parameters"]["byteLength"], 800); } @@ -1171,7 +1183,7 @@ mod tests { bytes.as_slice(), account_count, ); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(entry_code) @@ -1186,7 +1198,7 @@ mod tests { ); bytes.push(0); let result = decode(kb_program_ids::BPF_LOADER_UPGRADEABLE_PROGRAM_ID, bytes.as_slice(), 1); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("initialize_buffer") @@ -1243,7 +1255,7 @@ mod tests { for (bytes, account_count, entry_code) in fixtures { let result = decode(kb_program_ids::LOADER_V4_PROGRAM_ID, bytes.as_slice(), account_count); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(entry_code) @@ -1254,19 +1266,19 @@ mod tests { #[test] fn malformed_lengths_unknown_tags_and_invalid_boole_are_safe() { let truncated = decode(kb_program_ids::BPF_LOADER_PROGRAM_ID, &[0, 0, 0], 1); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut mismatched = immutable_write(0, 0, &[1, 2]); mismatched[8] = 3; let mismatched_result = decode(kb_program_ids::BPF_LOADER_PROGRAM_ID, mismatched.as_slice(), 1); - assert_eq!(mismatched_result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(mismatched_result.status, crate::DcApiDecoderOutcomeStatus::Failed); let unknown = decode(kb_program_ids::LOADER_V4_PROGRAM_ID, unit(99).as_slice(), 0); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); let mut invalid_bool = unit(3); invalid_bool.push(2); let invalid_bool_result = decode(kb_program_ids::BPF_LOADER_UPGRADEABLE_PROGRAM_ID, invalid_bool.as_slice(), 7); - assert_eq!(invalid_bool_result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(invalid_bool_result.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] @@ -1275,18 +1287,18 @@ mod tests { bytes.extend_from_slice(&128_u32.to_le_bytes()); let incomplete = decode(kb_program_ids::BPF_LOADER_UPGRADEABLE_PROGRAM_ID, bytes.as_slice(), 3); - assert_eq!(incomplete.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(incomplete.status, crate::DcApiDecoderOutcomeStatus::Failed); let complete = decode(kb_program_ids::BPF_LOADER_UPGRADEABLE_PROGRAM_ID, bytes.as_slice(), 4); - assert_eq!(complete.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(complete.status, crate::DcApiDecoderOutcomeStatus::Decoded); } #[test] fn failed_loader_lifecycle_is_uncommitted() { let bytes = unit(3); let input = replay_input(kb_program_ids::LOADER_V4_PROGRAM_ID, bytes.as_slice(), 2, true); - let result = crate::solana_core_loaders_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_loaders_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(result.observations[0].transaction_failed); assert!(!result.observations[0].observation_committed); } @@ -1294,14 +1306,14 @@ mod tests { #[test] fn native_loader_direct_invocation_is_ignored_without_false_event() { let input = replay_input(kb_program_ids::NATIVE_LOADER_PROGRAM_ID, &[], 0, false); - let result = crate::solana_core_loaders_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Ignored); + let result = crate::decoder_solana_core_loaders_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Ignored); assert!(result.observations.is_empty()); } #[test] fn coverage_declares_every_loader_entry() { - let coverage = crate::solana_core_loaders_coverage(); + let coverage = crate::decoder_solana_core_loaders_coverage(); assert_eq!(coverage.len(), 20); assert!( coverage diff --git a/kb-lib/src/decoder/solana/core/payload.rs b/kb-lib/src/decoder/solana/core/payload.rs index 8b5507c..9a4ab8f 100644 --- a/kb-lib/src/decoder/solana/core/payload.rs +++ b/kb-lib/src/decoder/solana/core/payload.rs @@ -7,7 +7,7 @@ use base64::Engine; // rust-rules: trait-import use sha2::Digest; // rust-rules: trait-import /// One resolved outer instruction payload and its provenance relative to the target instruction. -pub(crate) struct ResolvedInstructionPayload { +pub(crate) struct DcSolanaCoreResolvedInstructionPayload { /// Numeric outer instruction index in the transaction message. pub(crate) instruction_index: usize, /// Stable outer instruction path retained by the core store. @@ -19,8 +19,8 @@ pub(crate) struct ResolvedInstructionPayload { } /// Decodes one retained base64 instruction payload with an explicit byte limit. -pub(crate) fn decode_instruction_data( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_decode_instruction_data( + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result> { let payload = match input.instruction_payload_json.as_ref() { std::option::Option::Some(value) => value, @@ -34,22 +34,22 @@ pub(crate) fn decode_instruction_data( } /// Resolves an Ed25519 or secp256r1 instruction reference using the official `u16::MAX` sentinel. -pub(crate) fn resolve_u16_instruction_payload( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_resolve_u16_instruction_payload( + input: &crate::MdCoreInstructionReplayInput, raw_instruction_index: u16, -) -> kb_core::Result { +) -> kb_core::Result { if raw_instruction_index == u16::MAX { - let target_index_result = crate::solana_core_target_outer_instruction_index(input); + let target_index_result = crate::decoder_solana_core_target_outer_instruction_index(input); let target_index = match target_index_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let bytes_result = crate::solana_core_decode_instruction_data(input); + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - return std::result::Result::Ok(crate::SolanaCoreResolvedInstructionPayload { + return std::result::Result::Ok(crate::DcSolanaCoreResolvedInstructionPayload { instruction_index: target_index, instruction_path: input.instruction_path.clone(), bytes, @@ -61,16 +61,16 @@ pub(crate) fn resolve_u16_instruction_payload( /// Resolves a secp256k1 instruction reference. The runtime format has no current-instruction /// sentinel: every `u8` value is an explicit outer instruction index. -pub(crate) fn resolve_u8_instruction_payload( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_resolve_u8_instruction_payload( + input: &crate::MdCoreInstructionReplayInput, raw_instruction_index: u8, -) -> kb_core::Result { +) -> kb_core::Result { return resolve_explicit_outer_instruction(input, usize::from(raw_instruction_index)); } /// Returns the numeric outer index of the target instruction. -pub(crate) fn target_outer_instruction_index( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_target_outer_instruction_index( + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result { if input.instruction_path.contains('/') { return std::result::Result::Err(kb_core::Error::invalid_state( @@ -87,7 +87,7 @@ pub(crate) fn target_outer_instruction_index( } /// Extracts one exact bounded byte slice with checked arithmetic. -pub(crate) fn bounded_slice<'a>( +pub(crate) fn decoder_solana_core_bounded_slice<'a>( bytes: &'a [u8], offset: usize, length: usize, @@ -113,29 +113,31 @@ pub(crate) fn bounded_slice<'a>( } /// Returns the decoded target payload length when retained and valid. -pub(crate) fn decoded_payload_length( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_decoded_payload_length( + input: &crate::MdCoreInstructionReplayInput, ) -> std::option::Option { - return crate::solana_core_decode_instruction_data(input) + return crate::decoder_solana_core_decode_instruction_data(input) .ok() .map(|bytes| return bytes.len()); } /// Returns the SHA-256 of the decoded target instruction data when available. -pub(crate) fn decoded_payload_sha256( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_decoded_payload_sha256( + input: &crate::MdCoreInstructionReplayInput, ) -> std::option::Option { - let bytes_result = crate::solana_core_decode_instruction_data(input); + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); return match bytes_result { std::result::Result::Ok(bytes) => { - std::option::Option::Some(crate::solana_core_hash_bytes(bytes.as_slice())) + std::option::Option::Some(crate::decoder_solana_core_hash_bytes(bytes.as_slice())) }, std::result::Result::Err(_error) => std::option::Option::None, }; } /// Returns a stable payload hash from core or computes it from retained JSON. -pub(crate) fn payload_hash(input: &crate::CoreInstructionReplayInput) -> std::string::String { +pub(crate) fn decoder_solana_core_payload_hash( + input: &crate::MdCoreInstructionReplayInput, +) -> std::string::String { if let std::option::Option::Some(value) = input.instruction_payload_hash.as_ref() { return value.clone(); } @@ -143,7 +145,7 @@ pub(crate) fn payload_hash(input: &crate::CoreInstructionReplayInput) -> std::st std::option::Option::Some(value) => value, std::option::Option::None => serde_json::Value::Null, }; - let hash_result = crate::deterministic_json_hash(&mut value); + let hash_result = crate::decoder_api_deterministic_json_hash(&mut value); return match hash_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => "payload_hash_unavailable".to_string(), @@ -151,8 +153,9 @@ pub(crate) fn payload_hash(input: &crate::CoreInstructionReplayInput) -> std::st } /// Reads one little-endian `u32` from an exact byte range. -pub(crate) fn read_u32_le(bytes: &[u8], offset: usize) -> kb_core::Result { - let slice_result = crate::solana_core_bounded_slice(bytes, offset, 4, "native instruction u32"); +pub(crate) fn decoder_solana_core_read_u32_le(bytes: &[u8], offset: usize) -> kb_core::Result { + let slice_result = + crate::decoder_solana_core_bounded_slice(bytes, offset, 4, "native instruction u32"); let slice = match slice_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), @@ -167,8 +170,9 @@ pub(crate) fn read_u32_le(bytes: &[u8], offset: usize) -> kb_core::Result { } /// Reads one little-endian `u64` from an exact byte range. -pub(crate) fn read_u64_le(bytes: &[u8], offset: usize) -> kb_core::Result { - let slice_result = crate::solana_core_bounded_slice(bytes, offset, 8, "native instruction u64"); +pub(crate) fn decoder_solana_core_read_u64_le(bytes: &[u8], offset: usize) -> kb_core::Result { + let slice_result = + crate::decoder_solana_core_bounded_slice(bytes, offset, 8, "native instruction u64"); let slice = match slice_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), @@ -183,7 +187,7 @@ pub(crate) fn read_u64_le(bytes: &[u8], offset: usize) -> kb_core::Result { } /// Returns the lowercase SHA-256 of one bounded byte slice. -pub(crate) fn hash_bytes(bytes: &[u8]) -> std::string::String { +pub(crate) fn decoder_solana_core_hash_bytes(bytes: &[u8]) -> std::string::String { let digest = sha2::Sha256::digest(bytes); let mut output = std::string::String::with_capacity(digest.len().saturating_mul(2)); for byte in digest { @@ -193,7 +197,7 @@ pub(crate) fn hash_bytes(bytes: &[u8]) -> std::string::String { } /// Returns a normalized lowercase hexadecimal prefix. -pub(crate) fn hexadecimal_prefix( +pub(crate) fn decoder_solana_core_hexadecimal_prefix( bytes: &[u8], count: usize, ) -> std::option::Option { @@ -209,21 +213,21 @@ pub(crate) fn hexadecimal_prefix( } /// Returns a hexadecimal prefix no longer than the available byte slice. -pub(crate) fn bounded_hexadecimal_prefix( +pub(crate) fn decoder_solana_core_bounded_hexadecimal_prefix( bytes: &[u8], maximum_count: usize, ) -> std::string::String { let count = std::cmp::min(bytes.len(), maximum_count); - return match crate::solana_core_hexadecimal_prefix(bytes, count) { + return match crate::decoder_solana_core_hexadecimal_prefix(bytes, count) { std::option::Option::Some(value) => value, std::option::Option::None => std::string::String::new(), }; } fn resolve_explicit_outer_instruction( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, instruction_index: usize, -) -> kb_core::Result { +) -> kb_core::Result { let entries = match input.outer_instructions_json.as_array() { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -232,7 +236,7 @@ fn resolve_explicit_outer_instruction( )); }, }; - let target_index_result = crate::solana_core_target_outer_instruction_index(input); + let target_index_result = crate::decoder_solana_core_target_outer_instruction_index(input); let target_index = match target_index_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), @@ -276,7 +280,7 @@ fn resolve_explicit_outer_instruction( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - return std::result::Result::Ok(crate::SolanaCoreResolvedInstructionPayload { + return std::result::Result::Ok(crate::DcSolanaCoreResolvedInstructionPayload { instruction_index, instruction_path, bytes, @@ -300,7 +304,7 @@ fn decode_payload_json( ))); }, }; - let maximum_encoded_length = crate::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES + let maximum_encoded_length = crate::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES .saturating_mul(4) .saturating_div(3) .saturating_add(4); @@ -318,10 +322,10 @@ fn decode_payload_json( ))); }, }; - if decoded.len() > crate::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES { + if decoded.len() > crate::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES { return std::result::Result::Err(kb_core::Error::invalid_state(format!( "{label} payload exceeds {} decoded bytes", - crate::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES + crate::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES ))); } return std::result::Result::Ok(decoded); diff --git a/kb-lib/src/decoder/solana/core/precompiles.rs b/kb-lib/src/decoder/solana/core/precompiles.rs index 523b554..9335e7d 100644 --- a/kb-lib/src/decoder/solana/core/precompiles.rs +++ b/kb-lib/src/decoder/solana/core/precompiles.rs @@ -41,34 +41,38 @@ struct U16PrecompileSpec { } /// Returns declared signature precompile coverage. -pub(crate) fn precompiles_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_precompiles_coverage() +-> std::vec::Vec { return vec![ - coverage_entry(kb_program_ids::ED25519_PROGRAM_ID, crate::SOLANA_CORE_ED25519_SURFACE_CODE), + coverage_entry( + kb_program_ids::ED25519_PROGRAM_ID, + crate::DC_SOLANA_CORE_ED25519_SURFACE_CODE, + ), coverage_entry( kb_program_ids::SECP256K1_PROGRAM_ID, - crate::SOLANA_CORE_SECP256K1_SURFACE_CODE, + crate::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE, ), coverage_entry( kb_program_ids::SECP256R1_PROGRAM_ID, - crate::SOLANA_CORE_SECP256R1_SURFACE_CODE, + crate::DC_SOLANA_CORE_SECP256R1_SURFACE_CODE, ), ]; } /// Recognizes one signature precompile instruction without resolving referenced data. -pub(crate) fn precompiles_recognize( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_solana_core_precompiles_recognize( + input: &crate::MdCoreInstructionReplayInput, priority: u16, -) -> crate::DecoderRecognition { +) -> crate::DcApiDecoderRecognition { let surface_code = match surface_code(input.program_id.as_str()) { std::option::Option::Some(value) => value, - std::option::Option::None => return crate::DecoderRecognition::incompatible(), + std::option::Option::None => return crate::DcApiDecoderRecognition::incompatible(), }; - let bytes_result = crate::solana_core_decode_instruction_data(input); + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some(surface_code.to_string()), @@ -81,9 +85,9 @@ pub(crate) fn precompiles_recognize( let discriminator_hex = if prefix_count == 0 { std::option::Option::None } else { - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), prefix_count) + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), prefix_count) }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( true, priority, std::option::Option::Some(surface_code.to_string()), @@ -93,16 +97,16 @@ pub(crate) fn precompiles_recognize( } /// Decodes one signature precompile instruction structurally without cryptographic recomputation. -pub(crate) fn precompiles_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { +pub(crate) fn decoder_solana_core_precompiles_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { if input.program_id == kb_program_ids::ED25519_PROGRAM_ID { return decode_u16_precompile( input, &U16PrecompileSpec { algorithm: "ed25519", - surface_code: crate::SOLANA_CORE_ED25519_SURFACE_CODE, - verification_key_size: crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, + surface_code: crate::DC_SOLANA_CORE_ED25519_SURFACE_CODE, + verification_key_size: crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, zero_signature_allowed: true, maximum_signatures: usize::from(u8::MAX), source: SOURCE_ED25519, @@ -117,15 +121,15 @@ pub(crate) fn precompiles_decode( input, &U16PrecompileSpec { algorithm: "secp256r1", - surface_code: crate::SOLANA_CORE_SECP256R1_SURFACE_CODE, - verification_key_size: crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, + surface_code: crate::DC_SOLANA_CORE_SECP256R1_SURFACE_CODE, + verification_key_size: crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, zero_signature_allowed: false, - maximum_signatures: crate::SOLANA_CORE_SECP256R1_MAX_SIGNATURES, + maximum_signatures: crate::DC_SOLANA_CORE_SECP256R1_MAX_SIGNATURES, source: SOURCE_SECP256R1, }, ); } - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( ENTRY_CODE, "signature_precompile_program_unsupported", "program id is not one of the three supported signature precompiles", @@ -133,10 +137,10 @@ pub(crate) fn precompiles_decode( } fn decode_u16_precompile( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, spec: &U16PrecompileSpec, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { @@ -225,7 +229,7 @@ fn decode_u16_precompile( format!("signatureCount={signature_count} exceeds maximum={}", spec.maximum_signatures), ); } - let table_bytes = match signature_count.checked_mul(crate::SOLANA_CORE_U16_OFFSETS_BYTES) { + let table_bytes = match signature_count.checked_mul(crate::DC_SOLANA_CORE_U16_OFFSETS_BYTES) { std::option::Option::Some(value) => value, std::option::Option::None => { return failed( @@ -260,7 +264,8 @@ fn decode_u16_precompile( } let mut parameters = std::vec::Vec::with_capacity(signature_count); for entry_index in 0..signature_count { - let relative_offset = match entry_index.checked_mul(crate::SOLANA_CORE_U16_OFFSETS_BYTES) { + let relative_offset = match entry_index.checked_mul(crate::DC_SOLANA_CORE_U16_OFFSETS_BYTES) + { std::option::Option::Some(value) => value, std::option::Option::None => { return failed( @@ -315,8 +320,10 @@ fn decode_u16_precompile( return decoded_result(input, spec.surface_code, spec.algorithm, spec.source, parameters); } -fn decode_secp256k1(input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +fn decode_secp256k1( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { @@ -365,13 +372,13 @@ fn decode_secp256k1(input: &crate::CoreInstructionReplayInput) -> crate::Decoder } return decoded_result( input, - crate::SOLANA_CORE_SECP256K1_SURFACE_CODE, + crate::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE, "secp256k1", SOURCE_SECP256K1, vec![zero_signature_parameters(input, "secp256k1", std::option::Option::None)], ); } - let table_bytes = match signature_count.checked_mul(crate::SOLANA_CORE_U8_OFFSETS_BYTES) { + let table_bytes = match signature_count.checked_mul(crate::DC_SOLANA_CORE_U8_OFFSETS_BYTES) { std::option::Option::Some(value) => value, std::option::Option::None => { return failed( @@ -406,7 +413,8 @@ fn decode_secp256k1(input: &crate::CoreInstructionReplayInput) -> crate::Decoder } let mut parameters = std::vec::Vec::with_capacity(signature_count); for entry_index in 0..signature_count { - let relative_offset = match entry_index.checked_mul(crate::SOLANA_CORE_U8_OFFSETS_BYTES) { + let relative_offset = match entry_index.checked_mul(crate::DC_SOLANA_CORE_U8_OFFSETS_BYTES) + { std::option::Option::Some(value) => value, std::option::Option::None => { return failed( @@ -459,7 +467,7 @@ fn decode_secp256k1(input: &crate::CoreInstructionReplayInput) -> crate::Decoder } return decoded_result( input, - crate::SOLANA_CORE_SECP256K1_SURFACE_CODE, + crate::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE, "secp256k1", SOURCE_SECP256K1, parameters, @@ -467,14 +475,14 @@ fn decode_secp256k1(input: &crate::CoreInstructionReplayInput) -> crate::Decoder } fn resolve_u16_entry( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, spec: &U16PrecompileSpec, signature_count: usize, padding: u8, entry_index: usize, offsets: &U16SignatureOffsets, ) -> kb_core::Result { - let signature_payload_result = crate::solana_core_resolve_u16_instruction_payload( + let signature_payload_result = crate::decoder_solana_core_resolve_u16_instruction_payload( input, offsets.signature_instruction_index, ); @@ -482,15 +490,16 @@ fn resolve_u16_entry( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let verification_key_payload_result = crate::solana_core_resolve_u16_instruction_payload( - input, - offsets.verification_key_instruction_index, - ); + let verification_key_payload_result = + crate::decoder_solana_core_resolve_u16_instruction_payload( + input, + offsets.verification_key_instruction_index, + ); let verification_key_payload = match verification_key_payload_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let message_payload_result = crate::solana_core_resolve_u16_instruction_payload( + let message_payload_result = crate::decoder_solana_core_resolve_u16_instruction_payload( input, offsets.message_instruction_index, ); @@ -498,17 +507,17 @@ fn resolve_u16_entry( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let signature_result = crate::solana_core_bounded_slice( + let signature_result = crate::decoder_solana_core_bounded_slice( signature_payload.bytes.as_slice(), usize::from(offsets.signature_offset), - crate::SOLANA_CORE_SIGNATURE_BYTES, + crate::DC_SOLANA_CORE_SIGNATURE_BYTES, "signature", ); let signature = match signature_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let verification_key_result = crate::solana_core_bounded_slice( + let verification_key_result = crate::decoder_solana_core_bounded_slice( verification_key_payload.bytes.as_slice(), usize::from(offsets.verification_key_offset), spec.verification_key_size, @@ -518,7 +527,7 @@ fn resolve_u16_entry( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let message_result = crate::solana_core_bounded_slice( + let message_result = crate::decoder_solana_core_bounded_slice( message_payload.bytes.as_slice(), usize::from(offsets.message_data_offset), usize::from(offsets.message_data_size), @@ -571,12 +580,12 @@ fn resolve_u16_entry( } fn resolve_u8_entry( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, signature_count: usize, entry_index: usize, offsets: &U8SignatureOffsets, ) -> kb_core::Result { - let signature_payload_result = crate::solana_core_resolve_u8_instruction_payload( + let signature_payload_result = crate::decoder_solana_core_resolve_u8_instruction_payload( input, offsets.signature_instruction_index, ); @@ -584,7 +593,7 @@ fn resolve_u8_entry( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let address_payload_result = crate::solana_core_resolve_u8_instruction_payload( + let address_payload_result = crate::decoder_solana_core_resolve_u8_instruction_payload( input, offsets.ethereum_address_instruction_index, ); @@ -592,16 +601,18 @@ fn resolve_u8_entry( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let message_payload_result = - crate::solana_core_resolve_u8_instruction_payload(input, offsets.message_instruction_index); + let message_payload_result = crate::decoder_solana_core_resolve_u8_instruction_payload( + input, + offsets.message_instruction_index, + ); let message_payload = match message_payload_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let signature_result = crate::solana_core_bounded_slice( + let signature_result = crate::decoder_solana_core_bounded_slice( signature_payload.bytes.as_slice(), usize::from(offsets.signature_offset), - crate::SOLANA_CORE_SIGNATURE_BYTES, + crate::DC_SOLANA_CORE_SIGNATURE_BYTES, "secp256k1 compact signature", ); let signature = match signature_result { @@ -609,7 +620,7 @@ fn resolve_u8_entry( std::result::Result::Err(error) => return std::result::Result::Err(error), }; let recovery_offset = match usize::from(offsets.signature_offset) - .checked_add(crate::SOLANA_CORE_SIGNATURE_BYTES) + .checked_add(crate::DC_SOLANA_CORE_SIGNATURE_BYTES) { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -618,7 +629,7 @@ fn resolve_u8_entry( )); }, }; - let recovery_result = crate::solana_core_bounded_slice( + let recovery_result = crate::decoder_solana_core_bounded_slice( signature_payload.bytes.as_slice(), recovery_offset, 1, @@ -636,17 +647,17 @@ fn resolve_u8_entry( )); }, }; - let address_result = crate::solana_core_bounded_slice( + let address_result = crate::decoder_solana_core_bounded_slice( address_payload.bytes.as_slice(), usize::from(offsets.ethereum_address_offset), - crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES, + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES, "secp256k1 Ethereum address", ); let address = match address_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let message_result = crate::solana_core_bounded_slice( + let message_result = crate::decoder_solana_core_bounded_slice( message_payload.bytes.as_slice(), usize::from(offsets.message_data_offset), usize::from(offsets.message_data_size), @@ -699,17 +710,17 @@ fn resolve_u8_entry( } fn read_u16_offsets(bytes: &[u8], offset: usize) -> kb_core::Result { - let table_result = crate::solana_core_bounded_slice( + let table_result = crate::decoder_solana_core_bounded_slice( bytes, offset, - crate::SOLANA_CORE_U16_OFFSETS_BYTES, + crate::DC_SOLANA_CORE_U16_OFFSETS_BYTES, "Ed25519 or secp256r1 offsets", ); let table = match table_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let array_result = <[u8; crate::SOLANA_CORE_U16_OFFSETS_BYTES]>::try_from(table); + let array_result = <[u8; crate::DC_SOLANA_CORE_U16_OFFSETS_BYTES]>::try_from(table); let array = match array_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { @@ -758,17 +769,17 @@ fn read_u16_offsets(bytes: &[u8], offset: usize) -> kb_core::Result kb_core::Result { - let table_result = crate::solana_core_bounded_slice( + let table_result = crate::decoder_solana_core_bounded_slice( bytes, offset, - crate::SOLANA_CORE_U8_OFFSETS_BYTES, + crate::DC_SOLANA_CORE_U8_OFFSETS_BYTES, "secp256k1 offsets", ); let table = match table_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let array_result = <[u8; crate::SOLANA_CORE_U8_OFFSETS_BYTES]>::try_from(table); + let array_result = <[u8; crate::DC_SOLANA_CORE_U8_OFFSETS_BYTES]>::try_from(table); let array = match array_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { @@ -805,14 +816,14 @@ fn read_u8_offsets(bytes: &[u8], offset: usize) -> kb_core::Result, -) -> crate::DecoderExecutionResult { - let payload_hash = crate::solana_core_payload_hash(input); - let instruction_data_sha256 = match crate::solana_core_decoded_payload_sha256(input) { +) -> crate::DcApiDecoderExecutionResult { + let payload_hash = crate::decoder_solana_core_payload_hash(input); + let instruction_data_sha256 = match crate::decoder_solana_core_decoded_payload_sha256(input) { std::option::Option::Some(value) => value, std::option::Option::None => "instruction_data_sha256_unavailable".to_string(), }; @@ -822,24 +833,24 @@ fn decoded_result( std::option::Option::Some(value) => value.to_string(), std::option::Option::None => "batch".to_string(), }; - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(input.instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode(crate::SOLANA_CORE_PROTOCOL_CODE.to_string()), - surface_code: crate::SurfaceCode(surface_code.to_string()), - event_code: crate::EventCode(format!("{surface_code}.{ENTRY_CODE}")), - event_name: crate::EventName(ENTRY_CODE.to_string()), - event_family: crate::EventFamily::Audit, - source_kind: crate::EventSourceKind::Instruction, - confidence: crate::DecoderConfidence::ManualExact, + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(input.instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode(crate::DC_SOLANA_CORE_PROTOCOL_CODE.to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{ENTRY_CODE}")), + event_name: crate::MdEventName(ENTRY_CODE.to_string()), + event_family: crate::MdEventFamily::Audit, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, }; - observations.push(crate::DecodedObservation { + observations.push(crate::DcApiDecodedObservation { event_key: format!("{ENTRY_CODE}:{entry_key}"), event, payload_json: serde_json::json!({ - "eventVersion": crate::SOLANA_CORE_NATIVE_EVENT_VERSION, + "eventVersion": crate::DC_SOLANA_CORE_NATIVE_EVENT_VERSION, "programId": input.program_id, "surfaceCode": surface_code, "entryCode": ENTRY_CODE, @@ -856,9 +867,9 @@ fn decoded_result( transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: !input.transaction_failed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::ExactLayout, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::ExactLayout, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: vec![ source.to_string(), "structural_decode_only:no_cryptographic_reverification".to_string(), @@ -867,8 +878,8 @@ fn decoded_result( }, }); } - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some(ENTRY_CODE.to_string()), observations, diagnostics: std::vec::Vec::new(), @@ -876,7 +887,7 @@ fn decoded_result( } fn zero_signature_parameters( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, algorithm: &str, padding: std::option::Option, ) -> serde_json::Value { @@ -902,15 +913,15 @@ fn zero_signature_parameters( fn component_summary(bytes: &[u8]) -> serde_json::Value { return serde_json::json!({ "length": bytes.len(), - "sha256": crate::solana_core_hash_bytes(bytes), - "hexPrefix": crate::solana_core_bounded_hexadecimal_prefix( + "sha256": crate::decoder_solana_core_hash_bytes(bytes), + "hexPrefix": crate::decoder_solana_core_bounded_hexadecimal_prefix( bytes, - crate::SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES, + crate::DC_SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES, ), }); } -fn runtime_verification(input: &crate::CoreInstructionReplayInput) -> &'static str { +fn runtime_verification(input: &crate::MdCoreInstructionReplayInput) -> &'static str { return if input.transaction_failed { "not_asserted_transaction_failed" } else { @@ -919,22 +930,26 @@ fn runtime_verification(input: &crate::CoreInstructionReplayInput) -> &'static s } fn failed( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, algorithm: &str, code: &str, entry_index: std::option::Option, detail: impl std::convert::Into, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let detail_value = detail.into(); let bounded_detail = detail_value.chars().take(512).collect::(); - let decoded_result = crate::solana_core_decode_instruction_data(input); + let decoded_result = crate::decoder_solana_core_decode_instruction_data(input); let (payload_length, signature_count, payload_sha256) = match decoded_result { std::result::Result::Ok(bytes) => { let count = match bytes.first() { std::option::Option::Some(value) => value.to_string(), std::option::Option::None => "absent".to_string(), }; - (bytes.len().to_string(), count, crate::solana_core_hash_bytes(bytes.as_slice())) + ( + bytes.len().to_string(), + count, + crate::decoder_solana_core_hash_bytes(bytes.as_slice()), + ) }, std::result::Result::Err(_error) => { ("unknown".to_string(), "unknown".to_string(), "unavailable".to_string()) @@ -944,21 +959,21 @@ fn failed( std::option::Option::Some(value) => value.to_string(), std::option::Option::None => "none".to_string(), }; - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(ENTRY_CODE), code, format!( "algorithm={algorithm}; signatureCount={signature_count}; entryIndex={entry}; payloadLength={payload_length}; payloadSha256={payload_sha256}; payloadContextHash={}; detail={bounded_detail}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); } -fn coverage_entry(program_id: &str, surface_code: &str) -> crate::DecoderCoverageDeclaration { - return crate::DecoderCoverageDeclaration { +fn coverage_entry(program_id: &str, surface_code: &str) -> crate::DcApiDecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: program_id.to_string(), surface_code: std::option::Option::Some(surface_code.to_string()), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: ENTRY_CODE.to_string(), discriminator_hex: std::option::Option::None, historical: false, @@ -967,13 +982,13 @@ fn coverage_entry(program_id: &str, surface_code: &str) -> crate::DecoderCoverag fn surface_code(program_id: &str) -> std::option::Option<&'static str> { if program_id == kb_program_ids::ED25519_PROGRAM_ID { - return std::option::Option::Some(crate::SOLANA_CORE_ED25519_SURFACE_CODE); + return std::option::Option::Some(crate::DC_SOLANA_CORE_ED25519_SURFACE_CODE); } if program_id == kb_program_ids::SECP256K1_PROGRAM_ID { - return std::option::Option::Some(crate::SOLANA_CORE_SECP256K1_SURFACE_CODE); + return std::option::Option::Some(crate::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE); } if program_id == kb_program_ids::SECP256R1_PROGRAM_ID { - return std::option::Option::Some(crate::SOLANA_CORE_SECP256R1_SURFACE_CODE); + return std::option::Option::Some(crate::DC_SOLANA_CORE_SECP256R1_SURFACE_CODE); } return std::option::Option::None; } @@ -985,7 +1000,7 @@ mod tests { target_bytes: std::vec::Vec, mut external: std::vec::Vec<(usize, std::vec::Vec)>, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { external.push((1, target_bytes.clone())); external.sort_by_key(|entry| return entry.0); let outer = external @@ -1001,11 +1016,11 @@ mod tests { bytes, ) }, - "payloadHash": crate::solana_core_hash_bytes(bytes), + "payloadHash": crate::decoder_solana_core_hash_bytes(bytes), }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:1", "signature", 42, @@ -1027,7 +1042,9 @@ mod tests { target_bytes.as_slice(), ) })), - std::option::Option::Some(crate::solana_core_hash_bytes(target_bytes.as_slice())), + std::option::Option::Some(crate::decoder_solana_core_hash_bytes( + target_bytes.as_slice(), + )), serde_json::Value::Array(outer), serde_json::json!([]), serde_json::json!([]), @@ -1040,9 +1057,9 @@ mod tests { } fn u16_current_payload(key_size: usize, message: &[u8], padding: u8) -> std::vec::Vec { - let table_end = 2 + crate::SOLANA_CORE_U16_OFFSETS_BYTES; + let table_end = 2 + crate::DC_SOLANA_CORE_U16_OFFSETS_BYTES; let signature_offset = table_end; - let key_offset = signature_offset + crate::SOLANA_CORE_SIGNATURE_BYTES; + let key_offset = signature_offset + crate::DC_SOLANA_CORE_SIGNATURE_BYTES; let message_offset = key_offset + key_size; let mut bytes = vec![1, padding]; push_u16(&mut bytes, u16_value(signature_offset)); @@ -1052,7 +1069,7 @@ mod tests { push_u16(&mut bytes, u16_value(message_offset)); push_u16(&mut bytes, u16_value(message.len())); push_u16(&mut bytes, u16::MAX); - bytes.extend(std::iter::repeat_n(0x11, crate::SOLANA_CORE_SIGNATURE_BYTES)); + bytes.extend(std::iter::repeat_n(0x11, crate::DC_SOLANA_CORE_SIGNATURE_BYTES)); bytes.extend(std::iter::repeat_n(0x22, key_size)); bytes.extend_from_slice(message); return bytes; @@ -1063,7 +1080,7 @@ mod tests { message: &[u8], ) -> (std::vec::Vec, std::vec::Vec) { let signature_offset = 0; - let key_offset = crate::SOLANA_CORE_SIGNATURE_BYTES; + let key_offset = crate::DC_SOLANA_CORE_SIGNATURE_BYTES; let message_offset = key_offset + key_size; let mut target = vec![1, 0]; push_u16(&mut target, u16_value(signature_offset)); @@ -1073,7 +1090,7 @@ mod tests { push_u16(&mut target, u16_value(message_offset)); push_u16(&mut target, u16_value(message.len())); push_u16(&mut target, 0); - let mut external = vec![0x31; crate::SOLANA_CORE_SIGNATURE_BYTES]; + let mut external = vec![0x31; crate::DC_SOLANA_CORE_SIGNATURE_BYTES]; external.extend(std::iter::repeat_n(0x32, key_size)); external.extend_from_slice(message); return (target, external); @@ -1082,7 +1099,7 @@ mod tests { fn u16_mixed_payload( key_size: usize, ) -> (std::vec::Vec, std::vec::Vec<(usize, std::vec::Vec)>) { - let signature_offset = 2 + crate::SOLANA_CORE_U16_OFFSETS_BYTES; + let signature_offset = 2 + crate::DC_SOLANA_CORE_U16_OFFSETS_BYTES; let mut target = vec![1, 0]; push_u16(&mut target, u16_value(signature_offset)); push_u16(&mut target, u16::MAX); @@ -1091,15 +1108,16 @@ mod tests { push_u16(&mut target, 0); push_u16(&mut target, 4); push_u16(&mut target, 2); - target.extend(std::iter::repeat_n(0x41, crate::SOLANA_CORE_SIGNATURE_BYTES)); + target.extend(std::iter::repeat_n(0x41, crate::DC_SOLANA_CORE_SIGNATURE_BYTES)); return (target, vec![(0, vec![0x42; key_size]), (2, vec![0x43, 0x44, 0x45, 0x46])]); } fn secp256k1_current_payload(message: &[u8]) -> std::vec::Vec { - let table_end = 1 + crate::SOLANA_CORE_U8_OFFSETS_BYTES; + let table_end = 1 + crate::DC_SOLANA_CORE_U8_OFFSETS_BYTES; let signature_offset = table_end; - let address_offset = signature_offset + crate::SOLANA_CORE_SIGNATURE_BYTES + 1; - let message_offset = address_offset + crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; + let address_offset = signature_offset + crate::DC_SOLANA_CORE_SIGNATURE_BYTES + 1; + let message_offset = + address_offset + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; let mut bytes = vec![1]; push_u16(&mut bytes, u16_value(signature_offset)); bytes.push(1); @@ -1108,18 +1126,21 @@ mod tests { push_u16(&mut bytes, u16_value(message_offset)); push_u16(&mut bytes, u16_value(message.len())); bytes.push(1); - bytes.extend(std::iter::repeat_n(0x51, crate::SOLANA_CORE_SIGNATURE_BYTES)); + bytes.extend(std::iter::repeat_n(0x51, crate::DC_SOLANA_CORE_SIGNATURE_BYTES)); bytes.push(2); - bytes - .extend(std::iter::repeat_n(0x52, crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES)); + bytes.extend(std::iter::repeat_n( + 0x52, + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES, + )); bytes.extend_from_slice(message); return bytes; } fn secp256k1_external_payload(message: &[u8]) -> (std::vec::Vec, std::vec::Vec) { let signature_offset = 0; - let address_offset = crate::SOLANA_CORE_SIGNATURE_BYTES + 1; - let message_offset = address_offset + crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; + let address_offset = crate::DC_SOLANA_CORE_SIGNATURE_BYTES + 1; + let message_offset = + address_offset + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; let mut target = vec![1]; push_u16(&mut target, u16_value(signature_offset)); target.push(0); @@ -1128,16 +1149,18 @@ mod tests { push_u16(&mut target, u16_value(message_offset)); push_u16(&mut target, u16_value(message.len())); target.push(0); - let mut external = vec![0x61; crate::SOLANA_CORE_SIGNATURE_BYTES]; + let mut external = vec![0x61; crate::DC_SOLANA_CORE_SIGNATURE_BYTES]; external.push(3); - external - .extend(std::iter::repeat_n(0x62, crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES)); + external.extend(std::iter::repeat_n( + 0x62, + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES, + )); external.extend_from_slice(message); return (target, external); } fn secp256k1_mixed_payload() -> (std::vec::Vec, std::vec::Vec<(usize, std::vec::Vec)>) { - let signature_offset = 1 + crate::SOLANA_CORE_U8_OFFSETS_BYTES; + let signature_offset = 1 + crate::DC_SOLANA_CORE_U8_OFFSETS_BYTES; let mut target = vec![1]; push_u16(&mut target, u16_value(signature_offset)); target.push(1); @@ -1146,24 +1169,24 @@ mod tests { push_u16(&mut target, 0); push_u16(&mut target, 4); target.push(2); - target.extend(std::iter::repeat_n(0x71, crate::SOLANA_CORE_SIGNATURE_BYTES)); + target.extend(std::iter::repeat_n(0x71, crate::DC_SOLANA_CORE_SIGNATURE_BYTES)); target.push(1); return ( target, vec![ - (0, vec![0x72; crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES]), + (0, vec![0x72; crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES]), (2, vec![0x73, 0x74, 0x75, 0x76]), ], ); } fn two_u16_entries(key_size: usize) -> std::vec::Vec { - let table_end = 2 + 2 * crate::SOLANA_CORE_U16_OFFSETS_BYTES; - let entry_size = crate::SOLANA_CORE_SIGNATURE_BYTES + key_size + 1; + let table_end = 2 + 2 * crate::DC_SOLANA_CORE_U16_OFFSETS_BYTES; + let entry_size = crate::DC_SOLANA_CORE_SIGNATURE_BYTES + key_size + 1; let mut bytes = vec![2, 0]; for index in 0..2 { let signature_offset = table_end + index * entry_size; - let key_offset = signature_offset + crate::SOLANA_CORE_SIGNATURE_BYTES; + let key_offset = signature_offset + crate::DC_SOLANA_CORE_SIGNATURE_BYTES; let message_offset = key_offset + key_size; push_u16(&mut bytes, u16_value(signature_offset)); push_u16(&mut bytes, u16::MAX); @@ -1176,7 +1199,7 @@ mod tests { for index in 0..2 { bytes.extend(std::iter::repeat_n( 0x80 + index as u8, - crate::SOLANA_CORE_SIGNATURE_BYTES, + crate::DC_SOLANA_CORE_SIGNATURE_BYTES, )); bytes.extend(std::iter::repeat_n(0x90 + index as u8, key_size)); bytes.push(index as u8); @@ -1185,17 +1208,17 @@ mod tests { } fn two_secp256k1_entries() -> std::vec::Vec { - let table_end = 1 + 2 * crate::SOLANA_CORE_U8_OFFSETS_BYTES; - let entry_size = crate::SOLANA_CORE_SIGNATURE_BYTES + let table_end = 1 + 2 * crate::DC_SOLANA_CORE_U8_OFFSETS_BYTES; + let entry_size = crate::DC_SOLANA_CORE_SIGNATURE_BYTES + 1 - + crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES + + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES + 1; let mut bytes = vec![2]; for index in 0..2 { let signature_offset = table_end + index * entry_size; - let address_offset = signature_offset + crate::SOLANA_CORE_SIGNATURE_BYTES + 1; + let address_offset = signature_offset + crate::DC_SOLANA_CORE_SIGNATURE_BYTES + 1; let message_offset = - address_offset + crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; + address_offset + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; push_u16(&mut bytes, u16_value(signature_offset)); bytes.push(1); push_u16(&mut bytes, u16_value(address_offset)); @@ -1207,12 +1230,12 @@ mod tests { for index in 0..2 { bytes.extend(std::iter::repeat_n( 0xA0 + index as u8, - crate::SOLANA_CORE_SIGNATURE_BYTES, + crate::DC_SOLANA_CORE_SIGNATURE_BYTES, )); bytes.push(index as u8); bytes.extend(std::iter::repeat_n( 0xB0 + index as u8, - crate::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES, + crate::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES, )); bytes.push(index as u8); } @@ -1254,7 +1277,7 @@ mod tests { }; } - fn parameters(result: &crate::DecoderExecutionResult) -> &serde_json::Value { + fn parameters(result: &crate::DcApiDecoderExecutionResult) -> &serde_json::Value { return &result.observations[0].payload_json["parameters"]; } @@ -1262,12 +1285,12 @@ mod tests { fn ed25519_current_reference_decodes_exact_component_sizes_and_padding() { let input = replay_input( kb_program_ids::ED25519_PROGRAM_ID, - u16_current_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"message", 7), + u16_current_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"message", 7), vec![], false, ); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(parameters(&result)["padding"], 7); assert_eq!(parameters(&result)["signature"]["length"], 64); assert_eq!(parameters(&result)["publicKey"]["length"], 32); @@ -1278,12 +1301,12 @@ mod tests { fn secp256r1_current_reference_decodes_compressed_public_key() { let input = replay_input( kb_program_ids::SECP256R1_PROGRAM_ID, - u16_current_payload(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"r1", 11), + u16_current_payload(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"r1", 11), vec![], false, ); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(parameters(&result)["padding"], 11); assert_eq!(parameters(&result)["publicKey"]["length"], 33); assert_eq!(parameters(&result)["signature"]["length"], 64); @@ -1297,8 +1320,8 @@ mod tests { vec![], false, ); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(parameters(&result)["recoveryId"], 2); assert_eq!(parameters(&result)["ethereumAddress"]["length"], 20); assert_eq!(parameters(&result)["rawInstructionIndexes"]["signatureInstructionIndex"], 1); @@ -1308,10 +1331,10 @@ mod tests { #[test] fn all_precompiles_resolve_external_outer_instruction_data() { let (ed_target, ed_external) = - u16_external_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"external"); + u16_external_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"external"); let (k1_target, k1_external) = secp256k1_external_payload(b"external"); let (r1_target, r1_external) = - u16_external_payload(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"external"); + u16_external_payload(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"external"); let cases = [ (kb_program_ids::ED25519_PROGRAM_ID, ed_target, ed_external), (kb_program_ids::SECP256K1_PROGRAM_ID, k1_target, k1_external), @@ -1319,8 +1342,8 @@ mod tests { ]; for (program_id, target, external) in cases { let input = replay_input(program_id, target, vec![(0, external)], false); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(parameters(&result)["provenance"]["message"], "outer_instruction"); assert_eq!( parameters(&result)["resolvedInstructionIndexes"]["messageInstructionIndex"], @@ -1332,10 +1355,10 @@ mod tests { #[test] fn all_precompiles_support_mixed_component_references() { let (ed_target, ed_external) = - u16_mixed_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES); + u16_mixed_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES); let (k1_target, k1_external) = secp256k1_mixed_payload(); let (r1_target, r1_external) = - u16_mixed_payload(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES); + u16_mixed_payload(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES); let cases = [ (kb_program_ids::ED25519_PROGRAM_ID, ed_target, ed_external), (kb_program_ids::SECP256K1_PROGRAM_ID, k1_target, k1_external), @@ -1343,8 +1366,8 @@ mod tests { ]; for (program_id, target, external) in cases { let input = replay_input(program_id, target, external, false); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(parameters(&result)["provenance"]["signature"], "current_instruction"); assert_eq!(parameters(&result)["provenance"]["message"], "outer_instruction"); } @@ -1355,17 +1378,17 @@ mod tests { let cases = [ ( kb_program_ids::ED25519_PROGRAM_ID, - two_u16_entries(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES), + two_u16_entries(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES), ), ( kb_program_ids::SECP256R1_PROGRAM_ID, - two_u16_entries(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES), + two_u16_entries(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES), ), ]; for (program_id, bytes) in cases { let input = replay_input(program_id, bytes, vec![], false); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations.len(), 2); assert_eq!(result.observations[1].event_key, "signature_verification:1"); } @@ -1379,8 +1402,8 @@ mod tests { vec![], false, ); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations.len(), 2); assert_eq!(parameters(&result)["entryCount"], 2); assert_eq!(result.observations[1].payload_json["parameters"]["recoveryId"], 1); @@ -1390,11 +1413,11 @@ mod tests { fn empty_and_large_messages_are_hashed_without_full_message_retention() { let empty_input = replay_input( kb_program_ids::ED25519_PROGRAM_ID, - u16_current_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"", 0), + u16_current_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"", 0), vec![], false, ); - let empty_result = crate::solana_core_precompiles_decode(&empty_input); + let empty_result = crate::decoder_solana_core_precompiles_decode(&empty_input); assert_eq!(parameters(&empty_result)["message"]["length"], 0); let large_message = vec![0xA5; 1_024]; let large_input = replay_input( @@ -1403,38 +1426,38 @@ mod tests { vec![], false, ); - let large_result = crate::solana_core_precompiles_decode(&large_input); + let large_result = crate::decoder_solana_core_precompiles_decode(&large_input); assert_eq!(parameters(&large_result)["message"]["length"], 1_024); assert!(parameters(&large_result)["message"].get("bytes").is_none()); assert_eq!( parameters(&large_result)["message"]["sha256"], - crate::solana_core_hash_bytes(large_message.as_slice()) + crate::decoder_solana_core_hash_bytes(large_message.as_slice()) ); } #[test] fn official_zero_signature_rules_are_preserved() { - let ed_result = crate::solana_core_precompiles_decode(&replay_input( + let ed_result = crate::decoder_solana_core_precompiles_decode(&replay_input( kb_program_ids::ED25519_PROGRAM_ID, vec![0, 9], vec![], false, )); - let k1_result = crate::solana_core_precompiles_decode(&replay_input( + let k1_result = crate::decoder_solana_core_precompiles_decode(&replay_input( kb_program_ids::SECP256K1_PROGRAM_ID, vec![0], vec![], false, )); - let r1_result = crate::solana_core_precompiles_decode(&replay_input( + let r1_result = crate::decoder_solana_core_precompiles_decode(&replay_input( kb_program_ids::SECP256R1_PROGRAM_ID, vec![0, 0], vec![], false, )); - assert_eq!(ed_result.status, crate::DecoderOutcomeStatus::Decoded); - assert_eq!(k1_result.status, crate::DecoderOutcomeStatus::Decoded); - assert_eq!(r1_result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(ed_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); + assert_eq!(k1_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); + assert_eq!(r1_result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert_eq!(parameters(&ed_result)["entryCount"], 0); assert!(parameters(&k1_result).get("padding").is_none()); } @@ -1450,13 +1473,13 @@ mod tests { (kb_program_ids::SECP256R1_PROGRAM_ID, vec![1, 0, 1]), ]; for (program_id, bytes) in cases { - let result = crate::solana_core_precompiles_decode(&replay_input( + let result = crate::decoder_solana_core_precompiles_decode(&replay_input( program_id, bytes, vec![], false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert_eq!(result.diagnostics.len(), 1); } } @@ -1469,13 +1492,13 @@ mod tests { (kb_program_ids::SECP256R1_PROGRAM_ID, vec![9, 0]), ]; for (program_id, bytes) in cases { - let result = crate::solana_core_precompiles_decode(&replay_input( + let result = crate::decoder_solana_core_precompiles_decode(&replay_input( program_id, bytes, vec![], false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -1487,13 +1510,13 @@ mod tests { (kb_program_ids::SECP256R1_PROGRAM_ID, malformed_u16_index()), ]; for (program_id, bytes) in cases { - let result = crate::solana_core_precompiles_decode(&replay_input( + let result = crate::decoder_solana_core_precompiles_decode(&replay_input( program_id, bytes, vec![], false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert!(result.diagnostics[0].message.contains("signatureCount=1")); assert!(result.diagnostics[0].message.contains("entryIndex=0")); assert!(result.diagnostics[0].message.contains("payloadSha256=")); @@ -1502,13 +1525,13 @@ mod tests { #[test] fn out_of_bounds_offsets_fail_for_all_precompiles() { - let mut ed = u16_current_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"x", 0); + let mut ed = u16_current_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"x", 0); ed[2] = 0xFF; ed[3] = 0xFF; let mut k1 = secp256k1_current_payload(b"x"); k1[1] = 0xFF; k1[2] = 0xFF; - let mut r1 = u16_current_payload(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"x", 0); + let mut r1 = u16_current_payload(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"x", 0); r1[10] = 0xFF; r1[11] = 0xFF; let cases = [ @@ -1517,25 +1540,25 @@ mod tests { (kb_program_ids::SECP256R1_PROGRAM_ID, r1), ]; for (program_id, bytes) in cases { - let result = crate::solana_core_precompiles_decode(&replay_input( + let result = crate::decoder_solana_core_precompiles_decode(&replay_input( program_id, bytes, vec![], false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } #[test] fn out_of_bounds_message_lengths_fail_for_all_precompiles() { - let mut ed = u16_current_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"x", 0); + let mut ed = u16_current_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"x", 0); ed[12] = 0xFF; ed[13] = 0xFF; let mut k1 = secp256k1_current_payload(b"x"); k1[9] = 0xFF; k1[10] = 0xFF; - let mut r1 = u16_current_payload(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"x", 0); + let mut r1 = u16_current_payload(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"x", 0); r1[12] = 0xFF; r1[13] = 0xFF; let cases = [ @@ -1544,29 +1567,30 @@ mod tests { (kb_program_ids::SECP256R1_PROGRAM_ID, r1), ]; for (program_id, bytes) in cases { - let result = crate::solana_core_precompiles_decode(&replay_input( + let result = crate::decoder_solana_core_precompiles_decode(&replay_input( program_id, bytes, vec![], false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } #[test] fn checked_slice_rejects_offset_length_addition_overflow() { - let result = crate::solana_core_bounded_slice(&[1, 2, 3], usize::MAX, 1, "overflow test"); + let result = + crate::decoder_solana_core_bounded_slice(&[1, 2, 3], usize::MAX, 1, "overflow test"); assert!(result.is_err()); } #[test] fn missing_or_invalid_external_base64_fails_for_all_precompiles() { let (ed_target, ed_external) = - u16_external_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"external"); + u16_external_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"external"); let (k1_target, k1_external) = secp256k1_external_payload(b"external"); let (r1_target, r1_external) = - u16_external_payload(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"external"); + u16_external_payload(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"external"); let cases = [ (kb_program_ids::ED25519_PROGRAM_ID, ed_target, ed_external), (kb_program_ids::SECP256K1_PROGRAM_ID, k1_target, k1_external), @@ -1576,13 +1600,13 @@ mod tests { let mut missing = replay_input(program_id, target.clone(), vec![(0, external.clone())], false); missing.outer_instructions_json[0]["payloadJson"] = serde_json::Value::Null; - let missing_result = crate::solana_core_precompiles_decode(&missing); - assert_eq!(missing_result.status, crate::DecoderOutcomeStatus::Failed); + let missing_result = crate::decoder_solana_core_precompiles_decode(&missing); + assert_eq!(missing_result.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut invalid = replay_input(program_id, target, vec![(0, external)], false); invalid.outer_instructions_json[0]["payloadJson"] = serde_json::json!({"dataBase64": "%%%"}); - let invalid_result = crate::solana_core_precompiles_decode(&invalid); - assert_eq!(invalid_result.status, crate::DecoderOutcomeStatus::Failed); + let invalid_result = crate::decoder_solana_core_precompiles_decode(&invalid); + assert_eq!(invalid_result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -1592,13 +1616,13 @@ mod tests { bytes[3] = u8::MAX; bytes[6] = u8::MAX; bytes[11] = u8::MAX; - let result = crate::solana_core_precompiles_decode(&replay_input( + let result = crate::decoder_solana_core_precompiles_decode(&replay_input( kb_program_ids::SECP256K1_PROGRAM_ID, bytes, vec![], false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert!(result.diagnostics[0].message.contains("outer instruction index is absent: 255")); } @@ -1606,12 +1630,12 @@ mod tests { fn failed_transaction_is_decoded_without_commit_or_runtime_validity_claim() { let input = replay_input( kb_program_ids::ED25519_PROGRAM_ID, - u16_current_payload(crate::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"failed", 0), + u16_current_payload(crate::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES, b"failed", 0), vec![], true, ); - let result = crate::solana_core_precompiles_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_precompiles_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!(parameters(&result)["runtimeVerification"], "not_asserted_transaction_failed"); assert_eq!(parameters(&result)["cryptographicReverificationPerformed"], false); @@ -1621,25 +1645,25 @@ mod tests { fn event_kind_and_serialization_are_stable() { let input = replay_input( kb_program_ids::SECP256R1_PROGRAM_ID, - u16_current_payload(crate::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"stable", 0), + u16_current_payload(crate::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES, b"stable", 0), vec![], false, ); - let first = crate::solana_core_precompiles_decode(&input); - let second = crate::solana_core_precompiles_decode(&input); + let first = crate::decoder_solana_core_precompiles_decode(&input); + let second = crate::decoder_solana_core_precompiles_decode(&input); assert_eq!(first, second); assert_eq!( first.observations[0].event.event_code.0, "solana_native_secp256r1.signature_verification" ); assert_eq!(parameters(&first)["runtimeVerification"], "accepted_in_successful_transaction"); - let decoded_bytes = match crate::solana_core_decode_instruction_data(&input) { + let decoded_bytes = match crate::decoder_solana_core_decode_instruction_data(&input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("unexpected payload error: {error}"), }; assert_eq!( first.observations[0].payload_json["instructionDataSha256"], - crate::solana_core_hash_bytes(decoded_bytes.as_slice()) + crate::decoder_solana_core_hash_bytes(decoded_bytes.as_slice()) ); let first_json_result = serde_json::to_string(&first); let first_json = match first_json_result { @@ -1656,7 +1680,7 @@ mod tests { #[test] fn coverage_declares_exactly_three_signature_precompile_surfaces() { - let coverage = crate::solana_core_precompiles_coverage(); + let coverage = crate::decoder_solana_core_precompiles_coverage(); assert_eq!(coverage.len(), 3); assert!(coverage.iter().all(|entry| return entry.entry_code == "signature_verification")); } diff --git a/kb-lib/src/decoder/solana/core/slashing.rs b/kb-lib/src/decoder/solana/core/slashing.rs index a5b5b4c..40754f5 100644 --- a/kb-lib/src/decoder/solana/core/slashing.rs +++ b/kb-lib/src/decoder/solana/core/slashing.rs @@ -9,36 +9,37 @@ const DUPLICATE_BLOCK_PROOF_INSTRUCTION_BYTES: usize = 305; const SIGNATURE_BYTES: usize = 64; const HASH_BYTES: usize = 32; const PUBKEY_BYTES: usize = 32; -const CLOSE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("violation_report", true, false), - crate::SolanaCoreAccountRole::new("destination", true, false), +const CLOSE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("violation_report", true, false), + crate::DcSolanaCoreAccountRole::new("destination", true, false), ]; -const DUPLICATE_BLOCK_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("proof_account", false, false), - crate::SolanaCoreAccountRole::new("violation_report", true, false), - crate::SolanaCoreAccountRole::new("instructions_sysvar", false, false), - crate::SolanaCoreAccountRole::new("system_program", false, false), +const DUPLICATE_BLOCK_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("proof_account", false, false), + crate::DcSolanaCoreAccountRole::new("violation_report", true, false), + crate::DcSolanaCoreAccountRole::new("instructions_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("system_program", false, false), ]; /// Returns declared Slashing Program instruction coverage. -pub(crate) fn slashing_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_slashing_coverage() +-> std::vec::Vec { return vec![ - crate::DecoderCoverageDeclaration { + crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::SLASHING_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_SLASHING_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_SLASHING_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: "close_violation_report".to_string(), discriminator_hex: std::option::Option::Some("00".to_string()), historical: false, }, - crate::DecoderCoverageDeclaration { + crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::SLASHING_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_SLASHING_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_SLASHING_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: "duplicate_block_proof".to_string(), discriminator_hex: std::option::Option::Some("01".to_string()), historical: false, @@ -47,18 +48,18 @@ pub(crate) fn slashing_coverage() -> std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_SLASHING_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_SLASHING_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_slashing_instruction".to_string()), std::option::Option::None, ); @@ -72,24 +73,24 @@ pub(crate) fn slashing_recognize( std::option::Option::Some(_value) => ("unknown_slashing_instruction", false), std::option::Option::None => ("malformed_slashing_instruction", false), }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( exact, priority, - std::option::Option::Some(crate::SOLANA_CORE_SLASHING_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_SLASHING_SURFACE_CODE.to_string()), std::option::Option::Some(entry_code.to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(1)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(1)), ); } /// Decodes one Slashing Program instruction. -pub(crate) fn slashing_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_slashing_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_slashing_instruction"), "slashing_payload_invalid", error.to_string(), @@ -99,7 +100,7 @@ pub(crate) fn slashing_decode( let tag = match bytes.first() { std::option::Option::Some(value) => *value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_slashing_instruction"), "slashing_payload_empty", "Slashing Program instruction payload is empty", @@ -109,45 +110,49 @@ pub(crate) fn slashing_decode( return match tag { 0 => decode_close_violation_report(input, bytes.as_slice()), 1 => decode_duplicate_block_proof(input, bytes.as_slice()), - _ => crate::solana_core_unsupported_result( + _ => crate::decoder_solana_core_unsupported_result( "unknown_slashing_instruction", "slashing_tag_unknown", format!( "unknown Slashing Program instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ), }; } fn decode_close_violation_report( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() != 1 { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_violation_report"), "slashing_close_size_invalid", format!("close_violation_report requires exactly 1 byte but received {}", bytes.len()), ); } - let accounts_result = - crate::solana_core_resolve_accounts(input, CLOSE_ROLES, 2, std::option::Option::None); + let accounts_result = crate::decoder_solana_core_resolve_accounts( + input, + CLOSE_ROLES, + 2, + std::option::Option::None, + ); let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_violation_report"), "slashing_close_accounts_invalid", error.to_string(), ); }, }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_SLASHING_SURFACE_CODE, + crate::DC_SOLANA_CORE_SLASHING_SURFACE_CODE, "close_violation_report", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, accounts, serde_json::json!({ @@ -164,11 +169,11 @@ fn decode_close_violation_report( } fn decode_duplicate_block_proof( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { if bytes.len() != DUPLICATE_BLOCK_PROOF_INSTRUCTION_BYTES { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("duplicate_block_proof"), "slashing_duplicate_block_size_invalid", format!( @@ -178,7 +183,7 @@ fn decode_duplicate_block_proof( ), ); } - let accounts_result = crate::solana_core_resolve_accounts( + let accounts_result = crate::decoder_solana_core_resolve_accounts( input, DUPLICATE_BLOCK_ROLES, 4, @@ -187,7 +192,7 @@ fn decode_duplicate_block_proof( let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("duplicate_block_proof"), "slashing_duplicate_block_accounts_invalid", error.to_string(), @@ -196,7 +201,7 @@ fn decode_duplicate_block_proof( }; let fixed_accounts_result = validate_duplicate_block_fixed_accounts(&accounts); if let std::result::Result::Err(error) = fixed_accounts_result { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("duplicate_block_proof"), "slashing_duplicate_block_fixed_account_invalid", error.to_string(), @@ -206,18 +211,18 @@ fn decode_duplicate_block_proof( let parameters = match parsed_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("duplicate_block_proof"), "slashing_duplicate_block_data_invalid", error.to_string(), ); }, }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_SLASHING_SURFACE_CODE, + crate::DC_SOLANA_CORE_SLASHING_SURFACE_CODE, "duplicate_block_proof", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, accounts, parameters, @@ -226,15 +231,15 @@ fn decode_duplicate_block_proof( } fn parse_duplicate_block_parameters( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], ) -> kb_core::Result { - let offset_result = crate::solana_core_read_u64_le(bytes, 1); + let offset_result = crate::decoder_solana_core_read_u64_le(bytes, 1); let offset = match offset_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let slot_result = crate::solana_core_read_u64_le(bytes, 9); + let slot_result = crate::decoder_solana_core_read_u64_le(bytes, 9); let slot = match slot_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), @@ -254,7 +259,7 @@ fn parse_duplicate_block_parameters( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let shred_1_root_result = crate::solana_core_bounded_slice( + let shred_1_root_result = crate::decoder_solana_core_bounded_slice( bytes, 113, HASH_BYTES, @@ -264,7 +269,7 @@ fn parse_duplicate_block_parameters( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let shred_1_signature_result = crate::solana_core_bounded_slice( + let shred_1_signature_result = crate::decoder_solana_core_bounded_slice( bytes, 145, SIGNATURE_BYTES, @@ -274,7 +279,7 @@ fn parse_duplicate_block_parameters( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let shred_2_root_result = crate::solana_core_bounded_slice( + let shred_2_root_result = crate::decoder_solana_core_bounded_slice( bytes, 209, HASH_BYTES, @@ -284,7 +289,7 @@ fn parse_duplicate_block_parameters( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - let shred_2_signature_result = crate::solana_core_bounded_slice( + let shred_2_signature_result = crate::decoder_solana_core_bounded_slice( bytes, 241, SIGNATURE_BYTES, @@ -354,7 +359,7 @@ fn validate_duplicate_block_fixed_accounts(accounts: &serde_json::Value) -> kb_c } fn read_pubkey(bytes: &[u8], offset: usize, label: &str) -> kb_core::Result { - let slice_result = crate::solana_core_bounded_slice(bytes, offset, PUBKEY_BYTES, label); + let slice_result = crate::decoder_solana_core_bounded_slice(bytes, offset, PUBKEY_BYTES, label); return match slice_result { std::result::Result::Ok(value) => { std::result::Result::Ok(bs58::encode(value).into_string()) @@ -366,24 +371,24 @@ fn read_pubkey(bytes: &[u8], offset: usize, label: &str) -> kb_core::Result serde_json::Value { return serde_json::json!({ "length": bytes.len(), - "hex": crate::solana_core_bounded_hexadecimal_prefix(bytes, bytes.len()), - "sha256": crate::solana_core_hash_bytes(bytes), + "hex": crate::decoder_solana_core_bounded_hexadecimal_prefix(bytes, bytes.len()), + "sha256": crate::decoder_solana_core_hash_bytes(bytes), }); } fn signature_summary(bytes: &[u8]) -> serde_json::Value { return serde_json::json!({ "length": bytes.len(), - "prefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "prefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( bytes, - crate::SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES, + crate::DC_SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES, ), - "sha256": crate::solana_core_hash_bytes(bytes), + "sha256": crate::decoder_solana_core_hash_bytes(bytes), }); } -fn preceding_ed25519_instruction(input: &crate::CoreInstructionReplayInput) -> serde_json::Value { - let target_index = match crate::solana_core_target_outer_instruction_index(input) { +fn preceding_ed25519_instruction(input: &crate::MdCoreInstructionReplayInput) -> serde_json::Value { + let target_index = match crate::decoder_solana_core_target_outer_instruction_index(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { return serde_json::json!({ @@ -438,7 +443,7 @@ fn preceding_ed25519_instruction(input: &crate::CoreInstructionReplayInput) -> s } fn runtime_mutation( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, successful_value: &'static str, ) -> &'static str { return if input.transaction_failed { @@ -470,7 +475,7 @@ mod tests { bytes: &[u8], transaction_failed: bool, instruction_path: &str, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let keys = [ "Proof1111111111111111111111111111111111111", "Report111111111111111111111111111111111111", @@ -518,7 +523,7 @@ mod tests { "payloadHash": "slashing-hash" } ]); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{instruction_path}"), "signature", 42, @@ -547,7 +552,7 @@ mod tests { }; } - fn close_replay_input(transaction_failed: bool) -> crate::CoreInstructionReplayInput { + fn close_replay_input(transaction_failed: bool) -> crate::MdCoreInstructionReplayInput { let mut input = replay_input(&[0], transaction_failed, "0"); input.account_keys_json = serde_json::json!([ { @@ -576,7 +581,7 @@ mod tests { #[test] fn coverage_declares_exactly_two_official_instructions() { - let coverage = crate::solana_core_slashing_coverage(); + let coverage = crate::decoder_solana_core_slashing_coverage(); assert_eq!(coverage.len(), 2); assert_eq!(coverage[0].entry_code, "close_violation_report"); assert_eq!(coverage[1].entry_code, "duplicate_block_proof"); @@ -584,8 +589,8 @@ mod tests { #[test] fn close_violation_report_decodes_exact_runtime_contract() { - let result = crate::solana_core_slashing_decode(&close_replay_input(false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_slashing_decode(&close_replay_input(false)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("close_violation_report") @@ -602,9 +607,12 @@ mod tests { fn duplicate_block_proof_decodes_exact_official_layout() { let payload = duplicate_payload(); assert_eq!(payload.len(), super::DUPLICATE_BLOCK_PROOF_INSTRUCTION_BYTES); - let result = - crate::solana_core_slashing_decode(&replay_input(payload.as_slice(), false, "2")); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_slashing_decode(&replay_input( + payload.as_slice(), + false, + "2", + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let parameters = &result.observations[0].payload_json["parameters"]; assert_eq!(parameters["proofAccountOffset"], 34); assert_eq!(parameters["violationSlot"], 42); @@ -620,7 +628,7 @@ mod tests { #[test] fn duplicate_block_proof_reports_preceding_ed25519_context() { - let result = crate::solana_core_slashing_decode(&replay_input( + let result = crate::decoder_solana_core_slashing_decode(&replay_input( duplicate_payload().as_slice(), false, "2", @@ -636,12 +644,15 @@ mod tests { #[test] fn malformed_unknown_and_trailing_payloads_fail_safely() { for bytes in [vec![], vec![0, 7], vec![1, 2, 3]] { - let result = - crate::solana_core_slashing_decode(&replay_input(bytes.as_slice(), false, "2")); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = crate::decoder_solana_core_slashing_decode(&replay_input( + bytes.as_slice(), + false, + "2", + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } - let unknown = crate::solana_core_slashing_decode(&replay_input(&[9], false, "2")); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); + let unknown = crate::decoder_solana_core_slashing_decode(&replay_input(&[9], false, "2")); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); } #[test] @@ -649,18 +660,18 @@ mod tests { let mut input = replay_input(duplicate_payload().as_slice(), false, "2"); input.instruction_accounts_json[2]["accountKey"] = serde_json::json!("wrong"); input.account_keys_json[2]["accountKey"] = serde_json::json!("wrong"); - let result = crate::solana_core_slashing_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = crate::decoder_solana_core_slashing_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn failed_transaction_is_decoded_without_runtime_or_mutation_claim() { - let result = crate::solana_core_slashing_decode(&replay_input( + let result = crate::decoder_solana_core_slashing_decode(&replay_input( duplicate_payload().as_slice(), true, "2", )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); let parameters = &result.observations[0].payload_json["parameters"]; assert_eq!(parameters["runtimeVerification"], "not_asserted_transaction_failed"); @@ -670,8 +681,8 @@ mod tests { #[test] fn serialization_is_deterministic() { let input = replay_input(duplicate_payload().as_slice(), false, "2"); - let first = crate::solana_core_slashing_decode(&input); - let second = crate::solana_core_slashing_decode(&input); + let first = crate::decoder_solana_core_slashing_decode(&input); + let second = crate::decoder_solana_core_slashing_decode(&input); let first_json = match serde_json::to_string(&first) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("first serialization failed: {error}"), diff --git a/kb-lib/src/decoder/solana/core/stake.rs b/kb-lib/src/decoder/solana/core/stake.rs index e87964f..9200179 100644 --- a/kb-lib/src/decoder/solana/core/stake.rs +++ b/kb-lib/src/decoder/solana/core/stake.rs @@ -56,13 +56,14 @@ struct LockupCheckedArgsWire { } struct AccountContract { - roles: std::vec::Vec, + roles: std::vec::Vec, minimum_count: usize, account_layout: &'static str, } /// Returns declared Stake Program instruction coverage. -pub(crate) fn stake_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_stake_coverage() +-> std::vec::Vec { let entries = [ ("initialize", 0_u32, false), ("authorize", 1_u32, false), @@ -86,12 +87,12 @@ pub(crate) fn stake_coverage() -> std::vec::Vec std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_STAKE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_STAKE_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_stake_instruction".to_string()), std::option::Option::None, ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_STAKE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_STAKE_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_stake_instruction".to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), ); }, }; let entry_code = entry_code(tag); - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( entry_code.is_some(), priority, - std::option::Option::Some(crate::SOLANA_CORE_STAKE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_STAKE_SURFACE_CODE.to_string()), entry_code.map(str::to_string).or_else(|| { return std::option::Option::Some("unknown_stake_instruction".to_string()); }), @@ -144,25 +145,25 @@ pub(crate) fn stake_recognize( } /// Decodes one Stake Program instruction. -pub(crate) fn stake_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_stake_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_stake_instruction"), "stake_payload_invalid", error.to_string(), ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_stake_instruction"), "stake_tag_truncated", error.to_string(), @@ -172,12 +173,12 @@ pub(crate) fn stake_decode( let entry_code = match entry_code(tag) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_stake_instruction", "stake_tag_unknown", format!( "unknown Stake Program instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); }, @@ -186,7 +187,7 @@ pub(crate) fn stake_decode( let instruction = match instruction_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "stake_wincode_invalid", format!("cannot decode exact Stake Program {entry_code}: {error}"), @@ -197,14 +198,14 @@ pub(crate) fn stake_decode( } fn decoded_instruction( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, instruction: StakeInstructionWire, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { return match instruction { StakeInstructionWire::Initialize(authorized, lockup) => build( input, "initialize", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, contract(input, "initialize"), serde_json::json!({ @@ -215,7 +216,7 @@ fn decoded_instruction( StakeInstructionWire::Authorize(new_authority, authorization_type) => build( input, "authorize", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, contract(input, "authorize"), serde_json::json!({ @@ -226,7 +227,7 @@ fn decoded_instruction( StakeInstructionWire::DelegateStake => build( input, "delegate_stake", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "delegate_stake"), serde_json::json!({}), @@ -234,7 +235,7 @@ fn decoded_instruction( StakeInstructionWire::Split(lamports) => build( input, "split", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "split"), serde_json::json!({"lamports": lamports}), @@ -242,7 +243,7 @@ fn decoded_instruction( StakeInstructionWire::Withdraw(lamports) => build( input, "withdraw", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "withdraw"), serde_json::json!({"lamports": lamports}), @@ -250,7 +251,7 @@ fn decoded_instruction( StakeInstructionWire::Deactivate => build( input, "deactivate", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "deactivate"), serde_json::json!({}), @@ -258,7 +259,7 @@ fn decoded_instruction( StakeInstructionWire::SetLockup(value) => build( input, "set_lockup", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, contract(input, "set_lockup"), lockup_args_json(value), @@ -266,7 +267,7 @@ fn decoded_instruction( StakeInstructionWire::Merge => build( input, "merge", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "merge"), serde_json::json!({}), @@ -274,7 +275,7 @@ fn decoded_instruction( StakeInstructionWire::AuthorizeWithSeed(value) => build( input, "authorize_with_seed", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, contract(input, "authorize_with_seed"), serde_json::json!({ @@ -287,7 +288,7 @@ fn decoded_instruction( StakeInstructionWire::InitializeChecked => build( input, "initialize_checked", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, contract(input, "initialize_checked"), serde_json::json!({ @@ -298,7 +299,7 @@ fn decoded_instruction( StakeInstructionWire::AuthorizeChecked(authorization_type) => build( input, "authorize_checked", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, contract(input, "authorize_checked"), serde_json::json!({ @@ -309,7 +310,7 @@ fn decoded_instruction( StakeInstructionWire::AuthorizeCheckedWithSeed(value) => build( input, "authorize_checked_with_seed", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, contract(input, "authorize_checked_with_seed"), serde_json::json!({ @@ -322,7 +323,7 @@ fn decoded_instruction( StakeInstructionWire::SetLockupChecked(value) => build( input, "set_lockup_checked", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, contract(input, "set_lockup_checked"), lockup_checked_args_json(value), @@ -330,7 +331,7 @@ fn decoded_instruction( StakeInstructionWire::GetMinimumDelegation => build( input, "get_minimum_delegation", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, contract(input, "get_minimum_delegation"), serde_json::json!({ @@ -341,7 +342,7 @@ fn decoded_instruction( StakeInstructionWire::DeactivateDelinquent => build( input, "deactivate_delinquent", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "deactivate_delinquent"), serde_json::json!({}), @@ -349,7 +350,7 @@ fn decoded_instruction( StakeInstructionWire::Redelegate => build( input, "redelegate", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, true, contract(input, "redelegate"), serde_json::json!({ @@ -360,7 +361,7 @@ fn decoded_instruction( StakeInstructionWire::MoveStake(lamports) => build( input, "move_stake", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "move_stake"), serde_json::json!({"lamports": lamports}), @@ -368,7 +369,7 @@ fn decoded_instruction( StakeInstructionWire::MoveLamports(lamports) => build( input, "move_lamports", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, contract(input, "move_lamports"), serde_json::json!({"lamports": lamports}), @@ -377,14 +378,14 @@ fn decoded_instruction( } fn build( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, entry_code: &str, - event_family: crate::EventFamily, + event_family: crate::MdEventFamily, historical: bool, contract: AccountContract, mut parameters: serde_json::Value, -) -> crate::DecoderExecutionResult { - let accounts_result = crate::solana_core_resolve_accounts( +) -> crate::DcApiDecoderExecutionResult { + let accounts_result = crate::decoder_solana_core_resolve_accounts( input, contract.roles.as_slice(), contract.minimum_count, @@ -393,7 +394,7 @@ fn build( let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "stake_accounts_invalid", error.to_string(), @@ -406,9 +407,9 @@ fn build( serde_json::Value::String(contract.account_layout.to_string()), ); } - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_STAKE_SURFACE_CODE, + crate::DC_SOLANA_CORE_STAKE_SURFACE_CODE, entry_code, event_family, historical, @@ -418,7 +419,7 @@ fn build( ); } -fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> AccountContract { +fn contract(input: &crate::MdCoreInstructionReplayInput, entry_code: &str) -> AccountContract { return match entry_code { "initialize" => { if account_key(input, 1) @@ -426,15 +427,15 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco { AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), ], minimum_count: 1, account_layout: "legacy_rent_compatibility", } } else { AccountContract { - roles: vec![crate::SolanaCoreAccountRole::new("stake_account", true, false)], + roles: vec![crate::DcSolanaCoreAccountRole::new("stake_account", true, false)], minimum_count: 1, account_layout: "runtime_minimal", } @@ -444,16 +445,16 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 1, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 3, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 2, ), @@ -461,30 +462,30 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 2, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("vote_account", false, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("stake_history_sysvar", false, false), - crate::SolanaCoreAccountRole::new( + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("vote_account", false, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("stake_history_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new( "unused_stake_config_compatibility_account", false, false, ), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], 5, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("vote_account", false, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("vote_account", false, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], 3, ), "split" => AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("source_stake_account", true, false), - crate::SolanaCoreAccountRole::new("destination_stake_account", true, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("source_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("destination_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], minimum_count: 2, account_layout: "runtime_legacy_lax", @@ -493,19 +494,19 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 2, vec![ - crate::SolanaCoreAccountRole::new("source_stake_account", true, false), - crate::SolanaCoreAccountRole::new("recipient_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("stake_history_sysvar", false, false), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("source_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("recipient_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("stake_history_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 5, vec![ - crate::SolanaCoreAccountRole::new("source_stake_account", true, false), - crate::SolanaCoreAccountRole::new("recipient_account", true, false), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("source_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("recipient_account", true, false), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 3, ), @@ -513,21 +514,21 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 1, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], 2, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], 2, ), "set_lockup" => AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("lockup_or_withdraw_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("lockup_or_withdraw_authority", false, true), ], minimum_count: 1, account_layout: "runtime_legacy_lax", @@ -536,17 +537,17 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 2, vec![ - crate::SolanaCoreAccountRole::new("destination_stake_account", true, false), - crate::SolanaCoreAccountRole::new("source_stake_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("stake_history_sysvar", false, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("destination_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("source_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("stake_history_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], 4, vec![ - crate::SolanaCoreAccountRole::new("destination_stake_account", true, false), - crate::SolanaCoreAccountRole::new("source_stake_account", true, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("destination_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("source_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], 3, ), @@ -554,16 +555,16 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 2, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("authority_base", false, true), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority_base", false, true), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 3, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("authority_base", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority_base", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 2, ), @@ -573,10 +574,10 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco { AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, false), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, false), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), ], minimum_count: 4, account_layout: "legacy_sysvar", @@ -584,9 +585,9 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco } else { AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, false), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, false), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), ], minimum_count: 3, account_layout: "runtime_strict", @@ -597,18 +598,18 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 1, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 4, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 3, ), @@ -616,26 +617,26 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco input, 2, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("authority_base", false, true), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("new_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority_base", false, true), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 4, vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("authority_base", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, true), - crate::SolanaCoreAccountRole::new("lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("authority_base", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), + crate::DcSolanaCoreAccountRole::new("lockup_authority", false, true), ], 3, ), "set_lockup_checked" => AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("lockup_or_withdraw_authority", false, true), - crate::SolanaCoreAccountRole::new("new_lockup_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("lockup_or_withdraw_authority", false, true), + crate::DcSolanaCoreAccountRole::new("new_lockup_authority", false, true), ], minimum_count: 1, account_layout: "runtime_legacy_lax", @@ -647,33 +648,33 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco }, "deactivate_delinquent" => AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("stake_account", true, false), - crate::SolanaCoreAccountRole::new("delinquent_vote_account", false, false), - crate::SolanaCoreAccountRole::new("reference_vote_account", false, false), + crate::DcSolanaCoreAccountRole::new("stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("delinquent_vote_account", false, false), + crate::DcSolanaCoreAccountRole::new("reference_vote_account", false, false), ], minimum_count: 3, account_layout: "runtime_strict", }, "redelegate" => AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("source_stake_account", true, false), - crate::SolanaCoreAccountRole::new("destination_stake_account", true, false), - crate::SolanaCoreAccountRole::new("vote_account", false, false), - crate::SolanaCoreAccountRole::new( + crate::DcSolanaCoreAccountRole::new("source_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("destination_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("vote_account", false, false), + crate::DcSolanaCoreAccountRole::new( "unused_stake_config_compatibility_account", false, false, ), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], minimum_count: 0, account_layout: "disabled_before_account_processing", }, "move_stake" | "move_lamports" => AccountContract { roles: vec![ - crate::SolanaCoreAccountRole::new("source_stake_account", true, false), - crate::SolanaCoreAccountRole::new("destination_stake_account", true, false), - crate::SolanaCoreAccountRole::new("stake_authority", false, true), + crate::DcSolanaCoreAccountRole::new("source_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("destination_stake_account", true, false), + crate::DcSolanaCoreAccountRole::new("stake_authority", false, true), ], minimum_count: 3, account_layout: "runtime_strict", @@ -687,11 +688,11 @@ fn contract(input: &crate::CoreInstructionReplayInput, entry_code: &str) -> Acco } fn clock_branch_contract( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, branch_position: usize, - legacy_roles: std::vec::Vec, + legacy_roles: std::vec::Vec, legacy_minimum_count: usize, - current_roles: std::vec::Vec, + current_roles: std::vec::Vec, current_minimum_count: usize, ) -> AccountContract { if account_key(input, branch_position) @@ -711,7 +712,7 @@ fn clock_branch_contract( } fn account_key( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, position: usize, ) -> std::option::Option<&str> { return input @@ -1010,7 +1011,7 @@ mod tests { instruction: &super::StakeInstructionWire, account_keys: &[std::string::String], transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let bytes_result = wincode::serialize(instruction); let bytes = match bytes_result { std::result::Result::Ok(value) => value, @@ -1025,7 +1026,7 @@ mod tests { bytes: &[u8], account_keys: &[std::string::String], transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let resolved_keys = account_keys .iter() .enumerate() @@ -1050,7 +1051,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -1081,7 +1082,7 @@ mod tests { #[test] fn coverage_declares_every_official_stake_instruction() { - let coverage = crate::solana_core_stake_coverage(); + let coverage = crate::decoder_solana_core_stake_coverage(); assert_eq!(coverage.len(), 18); for tag in 0_u32..18_u32 { let expected = super::tag_hex(tag); @@ -1152,8 +1153,8 @@ mod tests { fixture.account_keys.as_slice(), fixture.transaction_failed, ); - let result = crate::solana_core_stake_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_stake_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(fixture.entry_code) @@ -1175,12 +1176,12 @@ mod tests { "Authority5".to_string(), ]; let current_keys = ["Stake0".to_string(), "Vote1".to_string(), "Authority2".to_string()]; - let legacy = crate::solana_core_stake_decode(&replay_input( + let legacy = crate::decoder_solana_core_stake_decode(&replay_input( &instruction, legacy_keys.as_slice(), false, )); - let current = crate::solana_core_stake_decode(&replay_input( + let current = crate::decoder_solana_core_stake_decode(&replay_input( &instruction, current_keys.as_slice(), false, @@ -1258,12 +1259,12 @@ mod tests { ]; for (instruction, keys) in fixtures { let account_keys = keys.into_iter().map(str::to_string).collect::>(); - let result = crate::solana_core_stake_decode(&replay_input( + let result = crate::decoder_solana_core_stake_decode(&replay_input( &instruction, account_keys.as_slice(), false, )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.observations[0].payload_json["parameters"]["accountLayout"], if matches!(instruction, super::StakeInstructionWire::Initialize(_, _)) { @@ -1279,8 +1280,8 @@ mod tests { fn deprecated_redelegate_is_an_uncommitted_historical_intent() { let instruction = super::StakeInstructionWire::Redelegate; let input = replay_input(&instruction, &[], true); - let result = crate::solana_core_stake_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_stake_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!(result.observations[0].payload_json["historical"], true); assert_eq!(result.observations[0].payload_json["parameters"]["officiallyDisabled"], true); @@ -1294,9 +1295,12 @@ mod tests { fn failed_stake_instruction_is_decoded_as_uncommitted_intent() { let instruction = super::StakeInstructionWire::MoveStake(42); let keys = ["Stake0".to_string(), "Stake1".to_string(), "Authority2".to_string()]; - let result = - crate::solana_core_stake_decode(&replay_input(&instruction, keys.as_slice(), true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_stake_decode(&replay_input( + &instruction, + keys.as_slice(), + true, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!(result.observations[0].payload_json["transactionSucceeded"], false); } @@ -1304,18 +1308,18 @@ mod tests { #[test] fn truncated_unknown_trailing_and_missing_accounts_fail_safely() { let no_accounts = std::vec::Vec::new(); - let truncated = crate::solana_core_stake_decode(&replay_input_bytes( + let truncated = crate::decoder_solana_core_stake_decode(&replay_input_bytes( &[0, 0, 0], no_accounts.as_slice(), false, )); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let unknown = crate::solana_core_stake_decode(&replay_input_bytes( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let unknown = crate::decoder_solana_core_stake_decode(&replay_input_bytes( &99_u32.to_le_bytes(), no_accounts.as_slice(), false, )); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); let bytes_result = wincode::serialize(&super::StakeInstructionWire::MoveLamports(1)); let mut bytes = match bytes_result { std::result::Result::Ok(value) => value, @@ -1324,12 +1328,12 @@ mod tests { }, }; bytes.push(1); - let trailing = crate::solana_core_stake_decode(&replay_input_bytes( + let trailing = crate::decoder_solana_core_stake_decode(&replay_input_bytes( bytes.as_slice(), no_accounts.as_slice(), false, )); - assert_eq!(trailing.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(trailing.status, crate::DcApiDecoderOutcomeStatus::Failed); let exact_result = wincode::serialize(&super::StakeInstructionWire::MoveLamports(1)); let exact = match exact_result { std::result::Result::Ok(value) => value, @@ -1337,11 +1341,11 @@ mod tests { panic!("Stake fixture serialization failed: {error}") }, }; - let missing_accounts = crate::solana_core_stake_decode(&replay_input_bytes( + let missing_accounts = crate::decoder_solana_core_stake_decode(&replay_input_bytes( exact.as_slice(), no_accounts.as_slice(), false, )); - assert_eq!(missing_accounts.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(missing_accounts.status, crate::DcApiDecoderOutcomeStatus::Failed); } } diff --git a/kb-lib/src/decoder/solana/core/system.rs b/kb-lib/src/decoder/solana/core/system.rs index 79c5a5d..b80e951 100644 --- a/kb-lib/src/decoder/solana/core/system.rs +++ b/kb-lib/src/decoder/solana/core/system.rs @@ -5,62 +5,63 @@ const SOURCE: &str = "solana-system-interface@3.2.0 SystemInstruction wincode-compatible contract"; -const CREATE_ACCOUNT_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("funding_account", true, true), - crate::SolanaCoreAccountRole::new("new_account", true, true), +const CREATE_ACCOUNT_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("funding_account", true, true), + crate::DcSolanaCoreAccountRole::new("new_account", true, true), ]; -const ASSIGN_ROLES: &[crate::SolanaCoreAccountRole] = - &[crate::SolanaCoreAccountRole::new("assigned_account", true, true)]; -const TRANSFER_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("funding_account", true, true), - crate::SolanaCoreAccountRole::new("recipient_account", true, false), +const ASSIGN_ROLES: &[crate::DcSolanaCoreAccountRole] = + &[crate::DcSolanaCoreAccountRole::new("assigned_account", true, true)]; +const TRANSFER_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("funding_account", true, true), + crate::DcSolanaCoreAccountRole::new("recipient_account", true, false), ]; -const CREATE_ACCOUNT_WITH_SEED_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("funding_account", true, true), - crate::SolanaCoreAccountRole::new("new_account", true, false), - crate::SolanaCoreAccountRole::new("base_account", false, true), +const CREATE_ACCOUNT_WITH_SEED_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("funding_account", true, true), + crate::DcSolanaCoreAccountRole::new("new_account", true, false), + crate::DcSolanaCoreAccountRole::new("base_account", false, true), ]; -const ADVANCE_NONCE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("nonce_account", true, false), - crate::SolanaCoreAccountRole::new("recent_blockhashes_sysvar", false, false), - crate::SolanaCoreAccountRole::new("nonce_authority", false, true), +const ADVANCE_NONCE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("nonce_account", true, false), + crate::DcSolanaCoreAccountRole::new("recent_blockhashes_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("nonce_authority", false, true), ]; -const WITHDRAW_NONCE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("nonce_account", true, false), - crate::SolanaCoreAccountRole::new("recipient_account", true, false), - crate::SolanaCoreAccountRole::new("recent_blockhashes_sysvar", false, false), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), - crate::SolanaCoreAccountRole::new("nonce_authority", false, true), +const WITHDRAW_NONCE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("nonce_account", true, false), + crate::DcSolanaCoreAccountRole::new("recipient_account", true, false), + crate::DcSolanaCoreAccountRole::new("recent_blockhashes_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("nonce_authority", false, true), ]; -const INITIALIZE_NONCE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("nonce_account", true, false), - crate::SolanaCoreAccountRole::new("recent_blockhashes_sysvar", false, false), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), +const INITIALIZE_NONCE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("nonce_account", true, false), + crate::DcSolanaCoreAccountRole::new("recent_blockhashes_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), ]; -const AUTHORIZE_NONCE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("nonce_account", true, false), - crate::SolanaCoreAccountRole::new("nonce_authority", false, true), +const AUTHORIZE_NONCE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("nonce_account", true, false), + crate::DcSolanaCoreAccountRole::new("nonce_authority", false, true), ]; -const ALLOCATE_ROLES: &[crate::SolanaCoreAccountRole] = - &[crate::SolanaCoreAccountRole::new("allocated_account", true, true)]; -const SEEDED_ACCOUNT_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("derived_account", true, false), - crate::SolanaCoreAccountRole::new("base_account", false, true), +const ALLOCATE_ROLES: &[crate::DcSolanaCoreAccountRole] = + &[crate::DcSolanaCoreAccountRole::new("allocated_account", true, true)]; +const SEEDED_ACCOUNT_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("derived_account", true, false), + crate::DcSolanaCoreAccountRole::new("base_account", false, true), ]; -const TRANSFER_WITH_SEED_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("funding_account", true, false), - crate::SolanaCoreAccountRole::new("base_account", false, true), - crate::SolanaCoreAccountRole::new("recipient_account", true, false), +const TRANSFER_WITH_SEED_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("funding_account", true, false), + crate::DcSolanaCoreAccountRole::new("base_account", false, true), + crate::DcSolanaCoreAccountRole::new("recipient_account", true, false), ]; -const UPGRADE_NONCE_ROLES: &[crate::SolanaCoreAccountRole] = - &[crate::SolanaCoreAccountRole::new("nonce_account", true, false)]; -const CREATE_ACCOUNT_ALLOW_PREFUND_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("new_account", true, true), - crate::SolanaCoreAccountRole::new("funding_account", true, true), +const UPGRADE_NONCE_ROLES: &[crate::DcSolanaCoreAccountRole] = + &[crate::DcSolanaCoreAccountRole::new("nonce_account", true, false)]; +const CREATE_ACCOUNT_ALLOW_PREFUND_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("new_account", true, true), + crate::DcSolanaCoreAccountRole::new("funding_account", true, true), ]; /// Returns declared System Program instruction coverage. -pub(crate) fn system_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_system_coverage() +-> std::vec::Vec { let entries = [ ("create_account", 0_u32), ("assign", 1_u32), @@ -80,12 +81,12 @@ pub(crate) fn system_coverage() -> std::vec::Vec std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_SYSTEM_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_system_instruction".to_string()), std::option::Option::None, ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_SYSTEM_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_system_instruction".to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), ); }, }; let entry_code = entry_code(tag); - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( entry_code.is_some(), priority, - std::option::Option::Some(crate::SOLANA_CORE_SYSTEM_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE.to_string()), entry_code.map(str::to_string).or_else(|| { return std::option::Option::Some("unknown_system_instruction".to_string()); }), @@ -138,25 +139,25 @@ pub(crate) fn system_recognize( } /// Decodes one System Program instruction. -pub(crate) fn system_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_system_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_system_instruction"), "system_payload_invalid", error.to_string(), ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_system_instruction"), "system_tag_truncated", error.to_string(), @@ -166,12 +167,12 @@ pub(crate) fn system_decode( let entry_code = match entry_code(tag) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_system_instruction", "system_tag_unknown", format!( "unknown System Program instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); }, @@ -182,7 +183,7 @@ pub(crate) fn system_decode( let instruction = match instruction_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "system_wincode_invalid", format!("cannot decode exact System Program {entry_code}: {error}"), @@ -193,9 +194,9 @@ pub(crate) fn system_decode( } fn decoded_instruction( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, instruction: solana_system_interface::instruction::SystemInstruction, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { return match instruction { solana_system_interface::instruction::SystemInstruction::CreateAccount { lamports, @@ -204,7 +205,7 @@ fn decoded_instruction( } => build( input, "create_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, CREATE_ACCOUNT_ROLES, 2, serde_json::json!({"lamports": lamports, "space": space, "owner": owner.to_string()}), @@ -212,7 +213,7 @@ fn decoded_instruction( solana_system_interface::instruction::SystemInstruction::Assign { owner } => build( input, "assign", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, ASSIGN_ROLES, 1, serde_json::json!({"owner": owner.to_string()}), @@ -220,7 +221,7 @@ fn decoded_instruction( solana_system_interface::instruction::SystemInstruction::Transfer { lamports } => build( input, "transfer", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, TRANSFER_ROLES, 2, serde_json::json!({"lamports": lamports}), @@ -234,7 +235,7 @@ fn decoded_instruction( } => build( input, "create_account_with_seed", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, CREATE_ACCOUNT_WITH_SEED_ROLES, 2, serde_json::json!({ @@ -248,7 +249,7 @@ fn decoded_instruction( solana_system_interface::instruction::SystemInstruction::AdvanceNonceAccount => build( input, "advance_nonce_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, ADVANCE_NONCE_ROLES, 3, serde_json::json!({}), @@ -257,7 +258,7 @@ fn decoded_instruction( build( input, "withdraw_nonce_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, WITHDRAW_NONCE_ROLES, 5, serde_json::json!({"lamports": lamports}), @@ -268,7 +269,7 @@ fn decoded_instruction( ) => build( input, "initialize_nonce_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, INITIALIZE_NONCE_ROLES, 3, serde_json::json!({"authority": authority.to_string()}), @@ -278,7 +279,7 @@ fn decoded_instruction( ) => build( input, "authorize_nonce_account", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, AUTHORIZE_NONCE_ROLES, 2, serde_json::json!({"authority": authority.to_string()}), @@ -286,7 +287,7 @@ fn decoded_instruction( solana_system_interface::instruction::SystemInstruction::Allocate { space } => build( input, "allocate", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, ALLOCATE_ROLES, 1, serde_json::json!({"space": space}), @@ -299,7 +300,7 @@ fn decoded_instruction( } => build( input, "allocate_with_seed", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, SEEDED_ACCOUNT_ROLES, 2, serde_json::json!({ @@ -316,7 +317,7 @@ fn decoded_instruction( } => build( input, "assign_with_seed", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, SEEDED_ACCOUNT_ROLES, 2, serde_json::json!({ @@ -332,7 +333,7 @@ fn decoded_instruction( } => build( input, "transfer_with_seed", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, TRANSFER_WITH_SEED_ROLES, 3, serde_json::json!({ @@ -344,7 +345,7 @@ fn decoded_instruction( solana_system_interface::instruction::SystemInstruction::UpgradeNonceAccount => build( input, "upgrade_nonce_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, UPGRADE_NONCE_ROLES, 1, serde_json::json!({}), @@ -356,7 +357,7 @@ fn decoded_instruction( } => build( input, "create_account_allow_prefund", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, CREATE_ACCOUNT_ALLOW_PREFUND_ROLES, if lamports == 0 { 1 } else { 2 }, serde_json::json!({"lamports": lamports, "space": space, "owner": owner.to_string()}), @@ -365,28 +366,32 @@ fn decoded_instruction( } fn build( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, entry_code: &str, - event_family: crate::EventFamily, - roles: &[crate::SolanaCoreAccountRole], + event_family: crate::MdEventFamily, + roles: &[crate::DcSolanaCoreAccountRole], minimum_count: usize, parameters: serde_json::Value, -) -> crate::DecoderExecutionResult { - let accounts_result = - crate::solana_core_resolve_accounts(input, roles, minimum_count, std::option::Option::None); +) -> crate::DcApiDecoderExecutionResult { + let accounts_result = crate::decoder_solana_core_resolve_accounts( + input, + roles, + minimum_count, + std::option::Option::None, + ); let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "system_accounts_invalid", error.to_string(), ); }, }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_SYSTEM_SURFACE_CODE, + crate::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE, entry_code, event_family, false, @@ -429,7 +434,7 @@ mod tests { instruction: &solana_system_interface::instruction::SystemInstruction, account_count: usize, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let bytes_result = wincode::serialize(instruction); let bytes = match bytes_result { std::result::Result::Ok(value) => value, @@ -444,7 +449,7 @@ mod tests { bytes: &[u8], account_count: usize, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let encoded = base64::engine::general_purpose::STANDARD.encode(bytes); let account_keys = (0..account_count) .map(|index| { @@ -466,7 +471,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -603,8 +608,8 @@ mod tests { ]; for (instruction, account_count, expected) in fixtures { let input = replay_input(&instruction, account_count, false); - let result = crate::solana_core_system_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_system_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -617,8 +622,9 @@ mod tests { fn additional_accounts_are_preserved_without_rejecting_valid_system_instructions() { let instruction = solana_system_interface::instruction::SystemInstruction::Transfer { lamports: 1 }; - let result = crate::solana_core_system_decode(&replay_input(&instruction, 3, false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = + crate::decoder_solana_core_system_decode(&replay_input(&instruction, 3, false)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let accounts = match result.observations[0].payload_json["accounts"].as_array() { std::option::Option::Some(value) => value, std::option::Option::None => panic!("decoded System accounts are not an array"), @@ -631,17 +637,22 @@ mod tests { fn missing_accounts_and_truncated_payload_fail_without_panic() { let instruction = solana_system_interface::instruction::SystemInstruction::Transfer { lamports: 1 }; - let missing = crate::solana_core_system_decode(&replay_input(&instruction, 1, false)); - assert_eq!(missing.status, crate::DecoderOutcomeStatus::Failed); - let truncated = crate::solana_core_system_decode(&replay_input_bytes(&[2, 0, 0], 2, false)); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); + let missing = + crate::decoder_solana_core_system_decode(&replay_input(&instruction, 1, false)); + assert_eq!(missing.status, crate::DcApiDecoderOutcomeStatus::Failed); + let truncated = + crate::decoder_solana_core_system_decode(&replay_input_bytes(&[2, 0, 0], 2, false)); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn unknown_tag_is_unsupported_and_hashable_for_replay() { - let result = - crate::solana_core_system_decode(&replay_input_bytes(&[255, 0, 0, 0], 0, false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported); + let result = crate::decoder_solana_core_system_decode(&replay_input_bytes( + &[255, 0, 0, 0], + 0, + false, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("unknown_system_instruction") @@ -652,8 +663,8 @@ mod tests { fn failed_transaction_is_decoded_as_uncommitted_intent() { let instruction = solana_system_interface::instruction::SystemInstruction::Transfer { lamports: 55 }; - let result = crate::solana_core_system_decode(&replay_input(&instruction, 2, true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_system_decode(&replay_input(&instruction, 2, true)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!(result.observations[0].payload_json["transactionSucceeded"], false); } @@ -663,8 +674,8 @@ mod tests { let instruction = solana_system_interface::instruction::SystemInstruction::Transfer { lamports: 55 }; let input = replay_input(&instruction, 2, false); - let first = crate::solana_core_system_decode(&input); - let second = crate::solana_core_system_decode(&input); + let first = crate::decoder_solana_core_system_decode(&input); + let second = crate::decoder_solana_core_system_decode(&input); let first_json = match serde_json::to_string(&first) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("first event serialization failed: {error}"), @@ -678,7 +689,7 @@ mod tests { #[test] fn coverage_declares_all_current_system_variants() { - let coverage = crate::solana_core_system_coverage(); + let coverage = crate::decoder_solana_core_system_coverage(); assert_eq!(coverage.len(), 14); assert!(coverage.iter().any(|entry| { return entry.entry_code == "create_account_allow_prefund" diff --git a/kb-lib/src/decoder/solana/core/vote.rs b/kb-lib/src/decoder/solana/core/vote.rs index ad787ed..03e2906 100644 --- a/kb-lib/src/decoder/solana/core/vote.rs +++ b/kb-lib/src/decoder/solana/core/vote.rs @@ -5,76 +5,77 @@ const SOURCE: &str = "solana-vote-interface@6.x VoteInstruction wincode contract"; -const INITIALIZE_ACCOUNT_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("rent_sysvar", false, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("validator_identity", false, true), +const INITIALIZE_ACCOUNT_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("rent_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("validator_identity", false, true), ]; -const AUTHORIZE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), +const AUTHORIZE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), ]; -const VOTE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("slot_hashes_sysvar", false, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("vote_authority", false, true), +const VOTE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("slot_hashes_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("vote_authority", false, true), ]; -const WITHDRAW_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("recipient_account", true, false), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), +const WITHDRAW_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("recipient_account", true, false), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), ]; -const UPDATE_VALIDATOR_IDENTITY_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("new_validator_identity", false, true), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), +const UPDATE_VALIDATOR_IDENTITY_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("new_validator_identity", false, true), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), ]; -const UPDATE_COMMISSION_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), +const UPDATE_COMMISSION_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), ]; -const AUTHORIZE_CHECKED_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("current_authority", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, true), +const AUTHORIZE_CHECKED_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("current_authority", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), ]; -const VOTE_STATE_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("vote_authority", false, true), +const VOTE_STATE_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("vote_authority", false, true), ]; -const AUTHORIZE_WITH_SEED_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("current_authority_base", false, true), +const AUTHORIZE_WITH_SEED_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("current_authority_base", false, true), ]; -const AUTHORIZE_CHECKED_WITH_SEED_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("clock_sysvar", false, false), - crate::SolanaCoreAccountRole::new("current_authority_base", false, true), - crate::SolanaCoreAccountRole::new("new_authority", false, true), +const AUTHORIZE_CHECKED_WITH_SEED_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("clock_sysvar", false, false), + crate::DcSolanaCoreAccountRole::new("current_authority_base", false, true), + crate::DcSolanaCoreAccountRole::new("new_authority", false, true), ]; -const INITIALIZE_ACCOUNT_V2_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("validator_identity", false, true), - crate::SolanaCoreAccountRole::new("inflation_rewards_collector", true, false), - crate::SolanaCoreAccountRole::new("block_revenue_collector", true, false), +const INITIALIZE_ACCOUNT_V2_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("validator_identity", false, true), + crate::DcSolanaCoreAccountRole::new("inflation_rewards_collector", true, false), + crate::DcSolanaCoreAccountRole::new("block_revenue_collector", true, false), ]; -const UPDATE_COMMISSION_COLLECTOR_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("new_commission_collector", true, false), - crate::SolanaCoreAccountRole::new("withdraw_authority", false, true), +const UPDATE_COMMISSION_COLLECTOR_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("new_commission_collector", true, false), + crate::DcSolanaCoreAccountRole::new("withdraw_authority", false, true), ]; -const DEPOSIT_DELEGATOR_REWARDS_ROLES: &[crate::SolanaCoreAccountRole] = &[ - crate::SolanaCoreAccountRole::new("vote_account", true, false), - crate::SolanaCoreAccountRole::new("deposit_source", true, true), +const DEPOSIT_DELEGATOR_REWARDS_ROLES: &[crate::DcSolanaCoreAccountRole] = &[ + crate::DcSolanaCoreAccountRole::new("vote_account", true, false), + crate::DcSolanaCoreAccountRole::new("deposit_source", true, true), ]; /// Returns declared Vote Program instruction coverage. -pub(crate) fn vote_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_vote_coverage() +-> std::vec::Vec { let entries = [ ("initialize_account", 0_u32), ("authorize", 1_u32), @@ -100,12 +101,12 @@ pub(crate) fn vote_coverage() -> std::vec::Vec std::vec::Vec crate::DecoderRecognition { - let bytes_result = crate::solana_core_decode_instruction_data(input); +) -> crate::DcApiDecoderRecognition { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_VOTE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_VOTE_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_vote_instruction".to_string()), std::option::Option::None, ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, - std::option::Option::Some(crate::SOLANA_CORE_VOTE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_VOTE_SURFACE_CODE.to_string()), std::option::Option::Some("malformed_vote_instruction".to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(4)), ); }, }; let entry_code = entry_code(tag); - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( entry_code.is_some(), priority, - std::option::Option::Some(crate::SOLANA_CORE_VOTE_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_VOTE_SURFACE_CODE.to_string()), entry_code.map(str::to_string).or_else(|| { return std::option::Option::Some("unknown_vote_instruction".to_string()); }), @@ -158,25 +159,25 @@ pub(crate) fn vote_recognize( } /// Decodes one Vote Program instruction. -pub(crate) fn vote_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes_result = crate::solana_core_decode_instruction_data(input); +pub(crate) fn decoder_solana_core_vote_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes_result = crate::decoder_solana_core_decode_instruction_data(input); let bytes = match bytes_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_vote_instruction"), "vote_payload_invalid", error.to_string(), ); }, }; - let tag_result = crate::solana_core_read_u32_le(bytes.as_slice(), 0); + let tag_result = crate::decoder_solana_core_read_u32_le(bytes.as_slice(), 0); let tag = match tag_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_vote_instruction"), "vote_tag_truncated", error.to_string(), @@ -186,12 +187,12 @@ pub(crate) fn vote_decode( let entry_code = match entry_code(tag) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_vote_instruction", "vote_tag_unknown", format!( "unknown Vote Program instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); }, @@ -202,7 +203,7 @@ pub(crate) fn vote_decode( let instruction = match instruction_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "vote_wincode_invalid", format!("cannot decode exact Vote Program {entry_code}: {error}"), @@ -213,14 +214,14 @@ pub(crate) fn vote_decode( } fn decoded_instruction( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, instruction: solana_vote_interface::instruction::VoteInstruction, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { return match instruction { solana_vote_interface::instruction::VoteInstruction::InitializeAccount(value) => build( input, "initialize_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, INITIALIZE_ACCOUNT_ROLES, 4, &[ @@ -235,7 +236,7 @@ fn decoded_instruction( ) => build( input, "authorize", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, AUTHORIZE_ROLES, 3, &[(1, kb_program_ids::SYSVAR_CLOCK_PROGRAM_ID)], @@ -247,7 +248,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::Vote(value) => build( input, "vote", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_ROLES, 4, &[ @@ -259,7 +260,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::Withdraw(lamports) => build( input, "withdraw", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, WITHDRAW_ROLES, 3, &[], @@ -268,7 +269,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::UpdateValidatorIdentity => build( input, "update_validator_identity", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, UPDATE_VALIDATOR_IDENTITY_ROLES, 3, &[], @@ -277,7 +278,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::UpdateCommission(commission) => build( input, "update_commission", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, UPDATE_COMMISSION_ROLES, 2, &[], @@ -293,7 +294,7 @@ fn decoded_instruction( build( input, "vote_switch", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_ROLES, 4, &[ @@ -308,7 +309,7 @@ fn decoded_instruction( ) => build( input, "authorize_checked", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, AUTHORIZE_CHECKED_ROLES, 4, &[(1, kb_program_ids::SYSVAR_CLOCK_PROGRAM_ID)], @@ -320,7 +321,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::UpdateVoteState(value) => build( input, "update_vote_state", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_STATE_ROLES, 2, &[], @@ -336,7 +337,7 @@ fn decoded_instruction( build( input, "update_vote_state_switch", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_STATE_ROLES, 2, &[], @@ -346,7 +347,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::AuthorizeWithSeed(value) => build( input, "authorize_with_seed", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, AUTHORIZE_WITH_SEED_ROLES, 3, &[(1, kb_program_ids::SYSVAR_CLOCK_PROGRAM_ID)], @@ -361,7 +362,7 @@ fn decoded_instruction( build( input, "authorize_checked_with_seed", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, AUTHORIZE_CHECKED_WITH_SEED_ROLES, 4, &[(1, kb_program_ids::SYSVAR_CLOCK_PROGRAM_ID)], @@ -377,7 +378,7 @@ fn decoded_instruction( build( input, "compact_update_vote_state", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_STATE_ROLES, 2, &[], @@ -394,7 +395,7 @@ fn decoded_instruction( build( input, "compact_update_vote_state_switch", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_STATE_ROLES, 2, &[], @@ -404,7 +405,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::TowerSync(value) => build( input, "tower_sync", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_STATE_ROLES, 2, &[], @@ -420,7 +421,7 @@ fn decoded_instruction( build( input, "tower_sync_switch", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, VOTE_STATE_ROLES, 2, &[], @@ -430,7 +431,7 @@ fn decoded_instruction( solana_vote_interface::instruction::VoteInstruction::InitializeAccountV2(value) => build( input, "initialize_account_v2", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, INITIALIZE_ACCOUNT_V2_ROLES, 4, &[], @@ -440,7 +441,7 @@ fn decoded_instruction( build( input, "update_commission_collector", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, UPDATE_COMMISSION_COLLECTOR_ROLES, 3, &[], @@ -453,7 +454,7 @@ fn decoded_instruction( } => build( input, "update_commission_bps", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, UPDATE_COMMISSION_ROLES, 2, &[], @@ -467,7 +468,7 @@ fn decoded_instruction( } => build( input, "deposit_delegator_rewards", - crate::EventFamily::Reward, + crate::MdEventFamily::Reward, DEPOSIT_DELEGATOR_REWARDS_ROLES, 2, &[], @@ -477,20 +478,24 @@ fn decoded_instruction( } fn build( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, entry_code: &str, - event_family: crate::EventFamily, - roles: &[crate::SolanaCoreAccountRole], + event_family: crate::MdEventFamily, + roles: &[crate::DcSolanaCoreAccountRole], minimum_count: usize, fixed_accounts: &[(usize, &str)], parameters: serde_json::Value, -) -> crate::DecoderExecutionResult { - let accounts_result = - crate::solana_core_resolve_accounts(input, roles, minimum_count, std::option::Option::None); +) -> crate::DcApiDecoderExecutionResult { + let accounts_result = crate::decoder_solana_core_resolve_accounts( + input, + roles, + minimum_count, + std::option::Option::None, + ); let accounts = match accounts_result { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "vote_accounts_invalid", error.to_string(), @@ -499,15 +504,15 @@ fn build( }; let fixed_result = validate_fixed_accounts(&accounts, fixed_accounts); if let std::result::Result::Err(error) = fixed_result { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(entry_code), "vote_fixed_account_invalid", error.to_string(), ); } - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_VOTE_SURFACE_CODE, + crate::DC_SOLANA_CORE_VOTE_SURFACE_CODE, entry_code, event_family, false, @@ -854,7 +859,7 @@ mod tests { account_count: usize, entry_code: &str, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let bytes_result = wincode::serialize(instruction); let bytes = match bytes_result { std::result::Result::Ok(value) => value, @@ -868,7 +873,7 @@ mod tests { account_count: usize, entry_code: &str, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let account_keys = (0..account_count) .map(|index| { let key = account_key(entry_code, index); @@ -890,7 +895,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -943,7 +948,7 @@ mod tests { #[test] fn coverage_declares_every_official_vote_instruction() { - let coverage = crate::solana_core_vote_coverage(); + let coverage = crate::decoder_solana_core_vote_coverage(); assert_eq!(coverage.len(), 20); for tag in 0_u32..20_u32 { let expected = super::tag_hex(tag); @@ -958,8 +963,8 @@ mod tests { fn every_official_vote_variant_decodes() { for (instruction, account_count, entry_code) in fixtures() { let input = replay_input(&instruction, account_count, entry_code, false); - let result = crate::solana_core_vote_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_vote_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(entry_code) @@ -978,8 +983,8 @@ mod tests { ), ); let input = replay_input(&instruction, 3, "authorize", false); - let result = crate::solana_core_vote_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_vote_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.observations[0].payload_json["parameters"]["authorizationType"]["kind"], "voter_with_bls" @@ -998,8 +1003,8 @@ mod tests { solana_vote_interface::state::VoteInitV2::default(), ); let input = replay_input(&instruction, 4, "initialize_account_v2", false); - let result = crate::solana_core_vote_decode(&input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_vote_decode(&input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let payload = &result.observations[0].payload_json; assert_eq!(payload["accounts"][2]["role"], "inflation_rewards_collector"); assert_eq!(payload["accounts"][3]["role"], "block_revenue_collector"); @@ -1009,20 +1014,20 @@ mod tests { #[test] fn truncated_unknown_and_trailing_payloads_are_distinguished() { - let truncated = crate::solana_core_vote_decode(&replay_input_bytes( + let truncated = crate::decoder_solana_core_vote_decode(&replay_input_bytes( &[0, 0, 0], 4, "initialize_account", false, )); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let unknown = crate::solana_core_vote_decode(&replay_input_bytes( + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let unknown = crate::decoder_solana_core_vote_decode(&replay_input_bytes( &[99, 0, 0, 0], 1, "unknown_vote_instruction", false, )); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); let fixture = solana_vote_interface::instruction::VoteInstruction::Withdraw(1); let bytes_result = wincode::serialize(&fixture); let mut bytes = match bytes_result { @@ -1030,13 +1035,13 @@ mod tests { std::result::Result::Err(error) => panic!("Vote fixture serialization failed: {error}"), }; bytes.push(0); - let trailing = crate::solana_core_vote_decode(&replay_input_bytes( + let trailing = crate::decoder_solana_core_vote_decode(&replay_input_bytes( bytes.as_slice(), 3, "withdraw", false, )); - assert_eq!(trailing.status, crate::DecoderOutcomeStatus::Failed); + assert_eq!(trailing.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] @@ -1044,24 +1049,25 @@ mod tests { let instruction = solana_vote_interface::instruction::VoteInstruction::Vote( solana_vote_interface::state::Vote::default(), ); - let missing = crate::solana_core_vote_decode(&replay_input(&instruction, 3, "vote", false)); - assert_eq!(missing.status, crate::DecoderOutcomeStatus::Failed); + let missing = + crate::decoder_solana_core_vote_decode(&replay_input(&instruction, 3, "vote", false)); + assert_eq!(missing.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut wrong = replay_input(&instruction, 4, "vote", false); wrong.instruction_accounts_json[1]["accountKey"] = serde_json::Value::String("WrongSysvar1111111111111111111111111111".to_string()); wrong.account_keys_json[1]["accountKey"] = serde_json::Value::String("WrongSysvar1111111111111111111111111111".to_string()); - let wrong_result = crate::solana_core_vote_decode(&wrong); - assert_eq!(wrong_result.status, crate::DecoderOutcomeStatus::Failed); + let wrong_result = crate::decoder_solana_core_vote_decode(&wrong); + assert_eq!(wrong_result.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn failed_vote_instruction_is_decoded_as_uncommitted_intent() { let instruction = solana_vote_interface::instruction::VoteInstruction::Withdraw(1); let input = replay_input(&instruction, 3, "withdraw", true); - let first = crate::solana_core_vote_decode(&input); - let second = crate::solana_core_vote_decode(&input); - assert_eq!(first.status, crate::DecoderOutcomeStatus::Decoded); + let first = crate::decoder_solana_core_vote_decode(&input); + let second = crate::decoder_solana_core_vote_decode(&input); + assert_eq!(first.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!first.observations[0].observation_committed); assert_eq!(first.observations[0].payload_json, second.observations[0].payload_json); } diff --git a/kb-lib/src/decoder/solana/core/zk_elgamal.rs b/kb-lib/src/decoder/solana/core/zk_elgamal.rs index e012db7..5d9c473 100644 --- a/kb-lib/src/decoder/solana/core/zk_elgamal.rs +++ b/kb-lib/src/decoder/solana/core/zk_elgamal.rs @@ -15,16 +15,17 @@ struct ProofDescriptor { } /// Returns declared ZK ElGamal Proof instruction coverage. -pub(crate) fn zk_elgamal_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_zk_elgamal_coverage() +-> std::vec::Vec { return instruction_entries() .iter() .map(|(tag, entry_code)| { - return crate::DecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::ZK_ELGAMAL_PROOF_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: (*entry_code).to_string(), discriminator_hex: std::option::Option::Some(format!("{tag:02x}")), historical: false, @@ -34,18 +35,18 @@ pub(crate) fn zk_elgamal_coverage() -> std::vec::Vec crate::DecoderRecognition { - let bytes = match crate::solana_core_decode_instruction_data(input) { +) -> crate::DcApiDecoderRecognition { + let bytes = match crate::decoder_solana_core_decode_instruction_data(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some( - crate::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), ), std::option::Option::Some("malformed_zk_elgamal_proof_instruction".to_string()), std::option::Option::None, @@ -63,14 +64,17 @@ pub(crate) fn zk_elgamal_recognize( } else { "unknown_zk_elgamal_proof_instruction" }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some( - crate::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), ), std::option::Option::Some(entry_code.to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(1)), + crate::decoder_solana_core_hexadecimal_prefix( + bytes.as_slice(), + bytes.len().min(1), + ), ); }, }; @@ -83,16 +87,16 @@ pub(crate) fn zk_elgamal_recognize( let descriptor = match descriptor { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some( - crate::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string(), ), std::option::Option::Some( "unknown_zk_elgamal_proof_instruction".to_string(), ), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), 1), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), 1), ); }, }; @@ -103,23 +107,23 @@ pub(crate) fn zk_elgamal_recognize( ) }, }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( exact, priority, - std::option::Option::Some(crate::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE.to_string()), std::option::Option::Some(entry_code.to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), 1), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), 1), ); } /// Decodes one native ZK ElGamal Proof instruction without recomputing the proof. -pub(crate) fn zk_elgamal_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes = match crate::solana_core_decode_instruction_data(input) { +pub(crate) fn decoder_solana_core_zk_elgamal_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes = match crate::decoder_solana_core_decode_instruction_data(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_zk_elgamal_proof_instruction"), "zk_elgamal_payload_invalid", error.to_string(), @@ -133,7 +137,7 @@ pub(crate) fn zk_elgamal_decode( std::option::Option::Some(value) => value, std::option::Option::None => { if bytes.is_empty() { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_zk_elgamal_proof_instruction"), "zk_elgamal_payload_empty", "ZK ElGamal Proof instruction payload is empty", @@ -142,19 +146,19 @@ pub(crate) fn zk_elgamal_decode( let tag = match bytes.first() { std::option::Option::Some(value) => *value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_zk_elgamal_proof_instruction"), "zk_elgamal_payload_empty", "ZK ElGamal Proof instruction payload is empty", ); }, }; - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_zk_elgamal_proof_instruction", "zk_elgamal_tag_unknown", format!( "unknown ZK ElGamal Proof instruction tag {tag}; payload_sha256={}", - crate::solana_core_payload_hash(input) + crate::decoder_solana_core_payload_hash(input) ), ); }, @@ -167,7 +171,7 @@ pub(crate) fn zk_elgamal_decode( let descriptor = match proof_descriptor(instruction) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_unsupported_result( + return crate::decoder_solana_core_unsupported_result( "unknown_zk_elgamal_proof_instruction", "zk_elgamal_instruction_unmapped", "official ZK ElGamal Proof instruction has no local descriptor", @@ -178,15 +182,15 @@ pub(crate) fn zk_elgamal_decode( } fn decode_close_context_state( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let roles = [ - crate::SolanaCoreAccountRole::new("proof_context_state", true, false), - crate::SolanaCoreAccountRole::new("lamport_destination", true, false), - crate::SolanaCoreAccountRole::new("context_state_authority", false, true), + crate::DcSolanaCoreAccountRole::new("proof_context_state", true, false), + crate::DcSolanaCoreAccountRole::new("lamport_destination", true, false), + crate::DcSolanaCoreAccountRole::new("context_state_authority", false, true), ]; - let accounts = match crate::solana_core_resolve_accounts( + let accounts = match crate::decoder_solana_core_resolve_accounts( input, roles.as_slice(), 3, @@ -194,7 +198,7 @@ fn decode_close_context_state( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_context_state"), "zk_elgamal_close_accounts_invalid", error.to_string(), @@ -204,7 +208,7 @@ fn decode_close_context_state( let account_array = match accounts.as_array() { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_context_state"), "zk_elgamal_close_accounts_not_array", "resolved ZK ElGamal close accounts are not an array", @@ -220,7 +224,7 @@ fn decode_close_context_state( .and_then(|value| return value.get("accountKey")) .and_then(serde_json::Value::as_str); if context_key.is_some() && context_key == destination_key { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_context_state"), "zk_elgamal_close_destination_matches_context", "ZK ElGamal proof context account and lamport destination must differ", @@ -229,26 +233,26 @@ fn decode_close_context_state( let trailing = match bytes.get(1..) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_context_state"), "zk_elgamal_close_payload_missing_tag", "ZK ElGamal close-context instruction has no discriminator byte", ); }, }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE, + crate::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE, "close_context_state", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, accounts, serde_json::json!({ "instructionMode": "close_context_state", "runtimeAcceptsTrailingBytes": true, "trailingByteLength": trailing.len(), - "trailingSha256": crate::solana_core_hash_bytes(trailing), - "trailingPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "trailingSha256": crate::decoder_solana_core_hash_bytes(trailing), + "trailingPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( trailing, PROOF_COMPONENT_PREFIX_BYTES, ), @@ -261,14 +265,14 @@ fn decode_close_context_state( } fn decode_verify_proof( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], descriptor: ProofDescriptor, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let external_proof = bytes.len() == PROOF_ACCOUNT_INSTRUCTION_BYTES; let expected_inline_size = descriptor.proof_data_size.saturating_add(1); if !external_proof && bytes.len() != expected_inline_size { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_elgamal_proof_data_size_invalid", format!( @@ -283,7 +287,7 @@ fn decode_verify_proof( let account_count = match input.instruction_accounts_json.as_array() { std::option::Option::Some(value) => value.len(), std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_elgamal_accounts_not_array", "ZK ElGamal Proof instruction accounts are not an array", @@ -294,14 +298,14 @@ fn decode_verify_proof( if external_proof { account_count >= 3 } else { account_count >= 2 }; let mut roles = std::vec::Vec::new(); if external_proof { - roles.push(crate::SolanaCoreAccountRole::new("proof_data_account", false, false)); + roles.push(crate::DcSolanaCoreAccountRole::new("proof_data_account", false, false)); } if context_state_requested { - roles.push(crate::SolanaCoreAccountRole::new("proof_context_state", true, false)); - roles.push(crate::SolanaCoreAccountRole::new("context_state_authority", false, false)); + roles.push(crate::DcSolanaCoreAccountRole::new("proof_context_state", true, false)); + roles.push(crate::DcSolanaCoreAccountRole::new("context_state_authority", false, false)); } let minimum_accounts = if external_proof { 1 } else { 0 }; - let accounts = match crate::solana_core_resolve_accounts( + let accounts = match crate::decoder_solana_core_resolve_accounts( input, roles.as_slice(), minimum_accounts, @@ -309,7 +313,7 @@ fn decode_verify_proof( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_elgamal_accounts_invalid", error.to_string(), @@ -317,10 +321,10 @@ fn decode_verify_proof( }, }; let proof_parameters = if external_proof { - let offset = match crate::solana_core_read_u32_le(bytes, 1) { + let offset = match crate::decoder_solana_core_read_u32_le(bytes, 1) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_elgamal_proof_account_offset_invalid", error.to_string(), @@ -342,7 +346,7 @@ fn decode_verify_proof( let proof_data = match bytes.get(1..) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_elgamal_inline_proof_missing", "inline ZK ElGamal proof data is missing", @@ -352,7 +356,7 @@ fn decode_verify_proof( let context_data = match proof_data.get(..descriptor.context_data_size) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_elgamal_inline_context_truncated", "inline ZK ElGamal proof context data is truncated", @@ -362,7 +366,7 @@ fn decode_verify_proof( let proof_body = match proof_data.get(descriptor.context_data_size..) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_elgamal_inline_proof_body_truncated", "inline ZK ElGamal proof body is truncated", @@ -376,28 +380,28 @@ fn decode_verify_proof( "proofDataByteLength": proof_data.len(), "contextDataByteLength": context_data.len(), "proofBodyByteLength": proof_body.len(), - "proofDataSha256": crate::solana_core_hash_bytes(proof_data), - "proofDataPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "proofDataSha256": crate::decoder_solana_core_hash_bytes(proof_data), + "proofDataPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( proof_data, PROOF_COMPONENT_PREFIX_BYTES, ), - "contextDataSha256": crate::solana_core_hash_bytes(context_data), - "contextDataPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "contextDataSha256": crate::decoder_solana_core_hash_bytes(context_data), + "contextDataPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( context_data, PROOF_COMPONENT_PREFIX_BYTES, ), - "proofBodySha256": crate::solana_core_hash_bytes(proof_body), - "proofBodyPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "proofBodySha256": crate::decoder_solana_core_hash_bytes(proof_body), + "proofBodyPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( proof_body, PROOF_COMPONENT_PREFIX_BYTES, ), }) }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE, + crate::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE, descriptor.entry_code, - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, accounts, serde_json::json!({ @@ -491,7 +495,7 @@ fn proof_descriptor( return std::option::Option::Some(descriptor); } -fn runtime_verification(input: &crate::CoreInstructionReplayInput) -> &'static str { +fn runtime_verification(input: &crate::MdCoreInstructionReplayInput) -> &'static str { if input.transaction_failed { return "not_asserted_transaction_failed"; } @@ -524,7 +528,7 @@ mod tests { bytes: &[u8], account_count: usize, transaction_failed: bool, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let account_keys = (0..account_count) .map(|index| { return serde_json::json!({ @@ -546,7 +550,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "signature:0", "signature", 42, @@ -590,7 +594,7 @@ mod tests { #[test] fn coverage_declares_all_thirteen_official_instructions() { - let coverage = crate::solana_core_zk_elgamal_coverage(); + let coverage = crate::decoder_solana_core_zk_elgamal_coverage(); assert_eq!(coverage.len(), 13); for (tag, entry_code) in super::instruction_entries() { let expected_discriminator = format!("{tag:02x}"); @@ -605,8 +609,10 @@ mod tests { #[test] fn official_discriminants_map_to_stable_entry_codes() { for (tag, entry_code) in super::instruction_entries() { - let recognition = - crate::solana_core_zk_elgamal_recognize(&replay_input(&[*tag], 3, false), 100); + let recognition = crate::decoder_solana_core_zk_elgamal_recognize( + &replay_input(&[*tag], 3, false), + 100, + ); assert!(recognition.compatible); assert_eq!(recognition.entry_code.as_deref(), std::option::Option::Some(*entry_code)); } @@ -615,8 +621,8 @@ mod tests { #[test] fn proof_account_mode_decodes_offset_and_context_request() { let bytes = [1_u8, 44, 0, 0, 0]; - let result = crate::solana_core_zk_elgamal_decode(&replay_input(&bytes, 3, false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_zk_elgamal_decode(&replay_input(&bytes, 3, false)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let parameters = &result.observations[0].payload_json["parameters"]; assert_eq!(parameters["proof"]["proofDataSource"], "account"); assert_eq!(parameters["proof"]["proofAccountOffset"], 44); @@ -628,8 +634,8 @@ mod tests { #[test] fn proof_account_mode_requires_the_proof_account() { let result = - crate::solana_core_zk_elgamal_decode(&replay_input(&[1, 0, 0, 0, 0], 0, false)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + crate::decoder_solana_core_zk_elgamal_decode(&replay_input(&[1, 0, 0, 0, 0], 0, false)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] @@ -650,9 +656,12 @@ mod tests { ]; for (tag, instruction) in variants { let bytes = inline_fixture(tag, instruction); - let result = - crate::solana_core_zk_elgamal_decode(&replay_input(bytes.as_slice(), 0, true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_zk_elgamal_decode(&replay_input( + bytes.as_slice(), + 0, + true, + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations.len(), 1); assert!(!result.observations[0].observation_committed); assert_eq!( @@ -664,18 +673,20 @@ mod tests { #[test] fn invalid_inline_sizes_unknown_tags_and_empty_payload_fail_safely() { - let truncated = crate::solana_core_zk_elgamal_decode(&replay_input(&[1, 2, 3], 0, false)); - assert_eq!(truncated.status, crate::DecoderOutcomeStatus::Failed); - let unknown = crate::solana_core_zk_elgamal_decode(&replay_input(&[99], 0, false)); - assert_eq!(unknown.status, crate::DecoderOutcomeStatus::Unsupported); - let empty = crate::solana_core_zk_elgamal_decode(&replay_input(&[], 0, false)); - assert_eq!(empty.status, crate::DecoderOutcomeStatus::Failed); + let truncated = + crate::decoder_solana_core_zk_elgamal_decode(&replay_input(&[1, 2, 3], 0, false)); + assert_eq!(truncated.status, crate::DcApiDecoderOutcomeStatus::Failed); + let unknown = crate::decoder_solana_core_zk_elgamal_decode(&replay_input(&[99], 0, false)); + assert_eq!(unknown.status, crate::DcApiDecoderOutcomeStatus::Unsupported); + let empty = crate::decoder_solana_core_zk_elgamal_decode(&replay_input(&[], 0, false)); + assert_eq!(empty.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn close_context_state_accepts_runtime_trailing_bytes_and_rejects_same_destination() { - let decoded = crate::solana_core_zk_elgamal_decode(&replay_input(&[0, 7, 8], 3, false)); - assert_eq!(decoded.status, crate::DecoderOutcomeStatus::Decoded); + let decoded = + crate::decoder_solana_core_zk_elgamal_decode(&replay_input(&[0, 7, 8], 3, false)); + assert_eq!(decoded.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(decoded.observations[0].payload_json["parameters"]["trailingByteLength"], 2); let mut same = replay_input(&[0], 3, false); let accounts = match same.instruction_accounts_json.as_array_mut() { @@ -688,14 +699,15 @@ mod tests { std::option::Option::None => panic!("account keys missing"), }; keys[1]["accountKey"] = keys[0]["accountKey"].clone(); - let failed = crate::solana_core_zk_elgamal_decode(&same); - assert_eq!(failed.status, crate::DecoderOutcomeStatus::Failed); + let failed = crate::decoder_solana_core_zk_elgamal_decode(&same); + assert_eq!(failed.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] fn failed_transaction_never_claims_runtime_verification_or_commit() { - let result = crate::solana_core_zk_elgamal_decode(&replay_input(&[4, 0, 0, 0, 0], 1, true)); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = + crate::decoder_solana_core_zk_elgamal_decode(&replay_input(&[4, 0, 0, 0, 0], 1, true)); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!( result.observations[0].payload_json["parameters"]["runtimeVerification"], @@ -706,8 +718,8 @@ mod tests { #[test] fn serialization_is_deterministic() { let input = replay_input(&[1, 0, 0, 0, 0], 1, false); - let first = crate::solana_core_zk_elgamal_decode(&input); - let second = crate::solana_core_zk_elgamal_decode(&input); + let first = crate::decoder_solana_core_zk_elgamal_decode(&input); + let second = crate::decoder_solana_core_zk_elgamal_decode(&input); let first_json = match serde_json::to_string(&first.observations[0].payload_json) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("first serialization failed: {error}"), diff --git a/kb-lib/src/decoder/solana/core/zk_token_proof.rs b/kb-lib/src/decoder/solana/core/zk_token_proof.rs index cdaef3f..7ef76e2 100644 --- a/kb-lib/src/decoder/solana/core/zk_token_proof.rs +++ b/kb-lib/src/decoder/solana/core/zk_token_proof.rs @@ -67,28 +67,29 @@ struct ProofDescriptor { } /// Returns declared historical and current ZK Token Proof coverage. -pub(crate) fn zk_token_proof_coverage() -> std::vec::Vec { +pub(crate) fn decoder_solana_core_zk_token_proof_coverage() +-> std::vec::Vec { let mut coverage = instruction_entries() .iter() .map(|(tag, entry_code)| { - return crate::DecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::ZK_TOKEN_PROOF_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: (*entry_code).to_string(), discriminator_hex: std::option::Option::Some(format!("{tag:02x}")), historical: true, }; }) .collect::>(); - coverage.push(crate::DecoderCoverageDeclaration { + coverage.push(crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::ZK_TOKEN_PROOF_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: "current_runtime_noop_invocation".to_string(), discriminator_hex: std::option::Option::None, historical: false, @@ -97,18 +98,18 @@ pub(crate) fn zk_token_proof_coverage() -> std::vec::Vec crate::DecoderRecognition { - let bytes = match crate::solana_core_decode_instruction_data(input) { +) -> crate::DcApiDecoderRecognition { + let bytes = match crate::decoder_solana_core_decode_instruction_data(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(_error) => { - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( false, priority, std::option::Option::Some( - crate::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string(), + crate::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string(), ), std::option::Option::Some("malformed_zk_token_proof_instruction".to_string()), std::option::Option::None, @@ -138,23 +139,23 @@ pub(crate) fn zk_token_proof_recognize( }, std::option::Option::None => "current_runtime_noop_invocation", }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( true, priority, - std::option::Option::Some(crate::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE.to_string()), std::option::Option::Some(entry_code.to_string()), - crate::solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(1)), + crate::decoder_solana_core_hexadecimal_prefix(bytes.as_slice(), bytes.len().min(1)), ); } /// Decodes one historical ZK Token Proof layout without recomputing any proof. -pub(crate) fn zk_token_proof_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes = match crate::solana_core_decode_instruction_data(input) { +pub(crate) fn decoder_solana_core_zk_token_proof_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes = match crate::decoder_solana_core_decode_instruction_data(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("malformed_zk_token_proof_instruction"), "zk_token_proof_payload_invalid", error.to_string(), @@ -184,7 +185,7 @@ pub(crate) fn zk_token_proof_decode( let inline_size = match descriptor.proof_data_size.checked_add(1) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_token_proof_inline_size_overflow", "historical ZK Token Proof inline size overflowed usize", @@ -198,26 +199,27 @@ pub(crate) fn zk_token_proof_decode( } fn decode_current_noop( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], historical_parse_status: &str, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let accounts = - match crate::solana_core_resolve_accounts(input, &[], 0, std::option::Option::None) { + match crate::decoder_solana_core_resolve_accounts(input, &[], 0, std::option::Option::None) + { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("current_runtime_noop_invocation"), "zk_token_proof_accounts_invalid", error.to_string(), ); }, }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE, + crate::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE, "current_runtime_noop_invocation", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, accounts, serde_json::json!({ @@ -225,8 +227,8 @@ fn decode_current_noop( "historicalParseStatus": historical_parse_status, "historicalDiscriminator": bytes.first().copied(), "payloadByteLength": bytes.len(), - "payloadSha256": crate::solana_core_hash_bytes(bytes), - "payloadPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "payloadSha256": crate::decoder_solana_core_hash_bytes(bytes), + "payloadPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( bytes, PROOF_COMPONENT_PREFIX_BYTES, ), @@ -244,15 +246,15 @@ fn decode_current_noop( } fn decode_close_context_state( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let roles = [ - crate::SolanaCoreAccountRole::new("proof_context_state", true, false), - crate::SolanaCoreAccountRole::new("lamport_destination", true, false), - crate::SolanaCoreAccountRole::new("context_state_authority", false, true), + crate::DcSolanaCoreAccountRole::new("proof_context_state", true, false), + crate::DcSolanaCoreAccountRole::new("lamport_destination", true, false), + crate::DcSolanaCoreAccountRole::new("context_state_authority", false, true), ]; - let accounts = match crate::solana_core_resolve_accounts( + let accounts = match crate::decoder_solana_core_resolve_accounts( input, roles.as_slice(), 0, @@ -260,7 +262,7 @@ fn decode_close_context_state( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_context_state"), "zk_token_proof_close_accounts_invalid", error.to_string(), @@ -270,7 +272,7 @@ fn decode_close_context_state( let account_array = match accounts.as_array() { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some("close_context_state"), "zk_token_proof_close_accounts_not_array", "resolved ZK Token Proof close accounts are not an array", @@ -293,11 +295,11 @@ fn decode_close_context_state( std::option::Option::Some(value) => value, std::option::Option::None => &[], }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE, + crate::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE, "close_context_state", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, true, accounts, serde_json::json!({ @@ -305,8 +307,8 @@ fn decode_close_context_state( "historicalAccountLayoutValid": historical_account_layout_valid, "historicalRuntimeAcceptsTrailingBytes": true, "trailingByteLength": trailing.len(), - "trailingSha256": crate::solana_core_hash_bytes(trailing), - "trailingPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "trailingSha256": crate::decoder_solana_core_hash_bytes(trailing), + "trailingPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( trailing, PROOF_COMPONENT_PREFIX_BYTES, ), @@ -326,15 +328,15 @@ fn decode_close_context_state( } fn decode_verify_proof( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], descriptor: ProofDescriptor, -) -> crate::DecoderExecutionResult { +) -> crate::DcApiDecoderExecutionResult { let external_proof = bytes.len() == PROOF_ACCOUNT_INSTRUCTION_BYTES; let account_count = match input.instruction_accounts_json.as_array() { std::option::Option::Some(value) => value.len(), std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_token_proof_accounts_not_array", "ZK Token Proof instruction accounts are not an array", @@ -346,13 +348,13 @@ fn decode_verify_proof( if external_proof { account_count >= 3 } else { account_count >= 2 }; let mut roles = std::vec::Vec::new(); if external_proof { - roles.push(crate::SolanaCoreAccountRole::new("proof_data_account", false, false)); + roles.push(crate::DcSolanaCoreAccountRole::new("proof_data_account", false, false)); } if context_state_requested { - roles.push(crate::SolanaCoreAccountRole::new("proof_context_state", true, false)); - roles.push(crate::SolanaCoreAccountRole::new("context_state_authority", false, false)); + roles.push(crate::DcSolanaCoreAccountRole::new("proof_context_state", true, false)); + roles.push(crate::DcSolanaCoreAccountRole::new("context_state_authority", false, false)); } - let accounts = match crate::solana_core_resolve_accounts( + let accounts = match crate::decoder_solana_core_resolve_accounts( input, roles.as_slice(), 0, @@ -360,7 +362,7 @@ fn decode_verify_proof( ) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_token_proof_accounts_invalid", error.to_string(), @@ -371,7 +373,7 @@ fn decode_verify_proof( { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_token_proof_official_size_inconsistent", "historical ZK Token Proof context size exceeds proof data size", @@ -379,10 +381,10 @@ fn decode_verify_proof( }, }; let proof_parameters = if external_proof { - let offset = match crate::solana_core_read_u32_le(bytes, 1) { + let offset = match crate::decoder_solana_core_read_u32_le(bytes, 1) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_token_proof_account_offset_invalid", error.to_string(), @@ -408,7 +410,7 @@ fn decode_verify_proof( let context_data = match proof_data.get(..descriptor.context_data_size) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_token_proof_inline_context_truncated", "inline historical ZK Token Proof context data is truncated", @@ -418,7 +420,7 @@ fn decode_verify_proof( let proof_body = match proof_data.get(descriptor.context_data_size..) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::solana_core_failed_result( + return crate::decoder_solana_core_failed_result( std::option::Option::Some(descriptor.entry_code), "zk_token_proof_inline_body_truncated", "inline historical ZK Token Proof body is truncated", @@ -432,18 +434,18 @@ fn decode_verify_proof( "proofDataByteLength": proof_data.len(), "contextDataByteLength": context_data.len(), "proofBodyByteLength": proof_body.len(), - "proofDataSha256": crate::solana_core_hash_bytes(proof_data), - "proofDataPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "proofDataSha256": crate::decoder_solana_core_hash_bytes(proof_data), + "proofDataPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( proof_data, PROOF_COMPONENT_PREFIX_BYTES, ), - "contextDataSha256": crate::solana_core_hash_bytes(context_data), - "contextDataPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "contextDataSha256": crate::decoder_solana_core_hash_bytes(context_data), + "contextDataPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( context_data, PROOF_COMPONENT_PREFIX_BYTES, ), - "proofBodySha256": crate::solana_core_hash_bytes(proof_body), - "proofBodyPrefixHex": crate::solana_core_bounded_hexadecimal_prefix( + "proofBodySha256": crate::decoder_solana_core_hash_bytes(proof_body), + "proofBodyPrefixHex": crate::decoder_solana_core_bounded_hexadecimal_prefix( proof_body, PROOF_COMPONENT_PREFIX_BYTES, ), @@ -454,11 +456,11 @@ fn decode_verify_proof( } else { descriptor.historical_inline_availability }; - return crate::solana_core_decoded_result( + return crate::decoder_solana_core_decoded_result( input, - crate::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE, + crate::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE, descriptor.entry_code, - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, true, accounts, serde_json::json!({ @@ -502,14 +504,14 @@ fn historical_account_layout(external_proof: bool, account_count: usize) -> &'st }; } -fn runtime_execution_outcome(input: &crate::CoreInstructionReplayInput) -> &'static str { +fn runtime_execution_outcome(input: &crate::MdCoreInstructionReplayInput) -> &'static str { if input.transaction_failed { return "not_asserted_transaction_failed"; } return "accepted_in_successful_transaction"; } -fn verification_claim(input: &crate::CoreInstructionReplayInput) -> &'static str { +fn verification_claim(input: &crate::MdCoreInstructionReplayInput) -> &'static str { if input.transaction_failed { return "not_asserted_transaction_failed"; } @@ -658,7 +660,7 @@ mod tests { account_count: usize, transaction_failed: bool, instruction_path: &str, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { let account_keys = (0..account_count) .map(|index| { return serde_json::json!({ @@ -680,7 +682,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{instruction_path}"), "signature", 42, @@ -728,7 +730,7 @@ mod tests { #[test] fn coverage_declares_seventeen_historical_entries_and_current_noop_fallback() { - let coverage = crate::solana_core_zk_token_proof_coverage(); + let coverage = crate::decoder_solana_core_zk_token_proof_coverage(); assert_eq!(coverage.len(), 18); assert_eq!(coverage.iter().filter(|entry| return entry.historical).count(), 17); assert!(coverage.iter().any(|entry| { @@ -742,7 +744,7 @@ mod tests { fn official_discriminants_map_to_stable_entry_codes() { for (tag, entry_code) in super::instruction_entries() { let bytes = if *tag == 0 { vec![*tag] } else { vec![*tag, 0, 0, 0, 0] }; - let recognition = crate::solana_core_zk_token_proof_recognize( + let recognition = crate::decoder_solana_core_zk_token_proof_recognize( &replay_input(bytes.as_slice(), 3, false, "0"), 100, ); @@ -795,13 +797,13 @@ mod tests { assert_eq!(descriptor.proof_data_size, proof_data_size); assert_eq!(descriptor.context_data_size, context_data_size); let bytes = inline_fixture(instruction); - let result = crate::solana_core_zk_token_proof_decode(&replay_input( + let result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( bytes.as_slice(), 0, true, "0", )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations.len(), 1); assert!(!result.observations[0].observation_committed); assert_eq!( @@ -813,13 +815,13 @@ mod tests { #[test] fn proof_account_mode_is_structured_and_historical_feature_gate_is_explicit() { - let result = crate::solana_core_zk_token_proof_decode(&replay_input( + let result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( &[1, 44, 0, 0, 0], 3, false, "0", )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let parameters = &result.observations[0].payload_json["parameters"]; assert_eq!(parameters["proof"]["proofDataSource"], "account"); assert_eq!(parameters["proof"]["proofAccountOffset"], 44); @@ -839,13 +841,13 @@ mod tests { ]; for instruction in variants { let bytes = inline_fixture(instruction); - let result = crate::solana_core_zk_token_proof_decode(&replay_input( + let result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( bytes.as_slice(), 0, false, "0", )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.observations[0].payload_json["parameters"]["historicalVariantAvailability"], "gated_by_enable_zk_transfer_with_fee" @@ -857,9 +859,10 @@ mod tests { fn malformed_historical_shapes_decode_as_current_noop_instead_of_false_failure() { let fixtures: &[&[u8]] = &[&[], &[99], &[1, 2, 3]]; for bytes in fixtures { - let result = - crate::solana_core_zk_token_proof_decode(&replay_input(bytes, 1, false, "0")); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( + bytes, 1, false, "0", + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("current_runtime_noop_invocation") @@ -878,23 +881,23 @@ mod tests { #[test] fn historical_account_arity_is_reported_without_overriding_current_noop_acceptance() { let inline = inline_fixture(super::HistoricalProofInstruction::VerifyZeroBalance); - let inline_result = crate::solana_core_zk_token_proof_decode(&replay_input( + let inline_result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( inline.as_slice(), 1, false, "0", )); - assert_eq!(inline_result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(inline_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(inline_result.observations[0].payload_json["parameters"]["historicalAccountLayoutValid"] .as_bool() .is_some_and(|value| return !value)); - let account_result = crate::solana_core_zk_token_proof_decode(&replay_input( + let account_result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( &[1, 0, 0, 0, 0], 2, false, "0", )); - assert_eq!(account_result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(account_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(account_result.observations[0].payload_json["parameters"]["historicalAccountLayoutValid"] .as_bool() .is_some_and(|value| return !value)); @@ -902,9 +905,13 @@ mod tests { #[test] fn close_context_state_preserves_historical_intent_without_claiming_mutation() { - let result = - crate::solana_core_zk_token_proof_decode(&replay_input(&[0, 7, 8], 3, false, "0")); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( + &[0, 7, 8], + 3, + false, + "0", + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let parameters = &result.observations[0].payload_json["parameters"]; assert!( parameters["historicalAccountLayoutValid"] @@ -924,13 +931,13 @@ mod tests { #[test] fn inner_invocation_never_claims_historical_verification() { let bytes = inline_fixture(super::HistoricalProofInstruction::VerifyPubkeyValidity); - let result = crate::solana_core_zk_token_proof_decode(&replay_input( + let result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( bytes.as_slice(), 0, false, "0/1", )); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!( result.observations[0].payload_json["parameters"]["historicalInnerInstructionSupport"] .as_bool() @@ -945,9 +952,13 @@ mod tests { #[test] fn failed_transaction_is_non_committed_and_never_claims_verification() { let bytes = inline_fixture(super::HistoricalProofInstruction::VerifyZeroBalance); - let result = - crate::solana_core_zk_token_proof_decode(&replay_input(bytes.as_slice(), 0, true, "0")); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::decoder_solana_core_zk_token_proof_decode(&replay_input( + bytes.as_slice(), + 0, + true, + "0", + )); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!( result.observations[0].payload_json["parameters"]["cryptographicVerificationClaim"], @@ -958,8 +969,8 @@ mod tests { #[test] fn serialization_is_deterministic() { let input = replay_input(&[1, 0, 0, 0, 0], 1, false, "0"); - let first = crate::solana_core_zk_token_proof_decode(&input); - let second = crate::solana_core_zk_token_proof_decode(&input); + let first = crate::decoder_solana_core_zk_token_proof_decode(&input); + let second = crate::decoder_solana_core_zk_token_proof_decode(&input); let first_json = match serde_json::to_string(&first.observations[0].payload_json) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("first serialization failed: {error}"), diff --git a/kb-lib/src/decoder/spl.rs b/kb-lib/src/decoder/spl.rs index aed2830..b91d2a1 100644 --- a/kb-lib/src/decoder/spl.rs +++ b/kb-lib/src/decoder/spl.rs @@ -3,142 +3,142 @@ //! `spl` decoder family. -pub mod account_compression; -pub mod associated_token_account; -pub mod elgamal_registry; -pub mod memo; -pub mod noop; -pub mod single_pool; -pub mod stake_pool; +mod account_compression; +mod associated_token_account; +mod elgamal_registry; +mod memo; +mod noop; +mod single_pool; +mod stake_pool; mod token; -pub mod token_2022; +mod token2022; /// Current stable Associated Token Account decoded event contract version. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_EVENT_VERSION; +pub(crate) use self::associated_token_account::DC_SPL_ATA_EVENT_VERSION; /// Exact Associated Token Account instructions published by the official interface. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES; +pub(crate) use self::associated_token_account::DC_SPL_ATA_INSTRUCTION_ENTRIES; /// Maximum retained account-key text length for the Associated Token Account decoder. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNT_KEY_BYTES; +pub(crate) use self::associated_token_account::DC_SPL_ATA_MAX_ACCOUNT_KEY_BYTES; /// Maximum retained instruction account count for the Associated Token Account decoder. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNTS; +pub(crate) use self::associated_token_account::DC_SPL_ATA_MAX_ACCOUNTS; /// Maximum retained semantic diagnostic count for the Associated Token Account decoder. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_DIAGNOSTICS; +pub(crate) use self::associated_token_account::DC_SPL_ATA_MAX_DIAGNOSTICS; /// Maximum retained Associated Token Account instruction payload size. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_INSTRUCTION_BYTES; +pub(crate) use self::associated_token_account::DC_SPL_ATA_MAX_INSTRUCTION_BYTES; /// Maximum retained transaction account-key count for the Associated Token Account decoder. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_TRANSACTION_KEYS; +pub(crate) use self::associated_token_account::DC_SPL_ATA_MAX_TRANSACTION_KEYS; /// Stable protocol and surface code for the Associated Token Account program. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE; +pub(crate) use self::associated_token_account::DC_SPL_ATA_SURFACE_CODE; /// Canonical tracing target for the Associated Token Account decoder. -pub(crate) use self::associated_token_account::SPL_ASSOCIATED_TOKEN_ACCOUNT_TRACING_TARGET; +pub(crate) use self::associated_token_account::DC_SPL_ATA_TRACING_TARGET; /// Decodes one bounded Associated Token Account instruction. -pub(crate) use self::associated_token_account::spl_associated_token_account_decode; +pub(crate) use self::associated_token_account::decoder_spl_associated_token_account_decode; /// Returns the exact entry matching an Associated Token Account wire. -pub(crate) use self::associated_token_account::spl_associated_token_account_entry; +pub(crate) use self::associated_token_account::decoder_spl_associated_token_account_entry; /// Reads one bounded Associated Token Account payload. -pub(crate) use self::associated_token_account::spl_associated_token_account_payload; -/// One parsed SPL ElGamal registry instruction. -pub(crate) use self::elgamal_registry::ParsedRegistryInstruction; +pub(crate) use self::associated_token_account::decoder_spl_associated_token_account_payload; /// Current stable SPL ElGamal registry event contract version. -pub(crate) use self::elgamal_registry::SPL_ELGAMAL_REGISTRY_EVENT_VERSION; +pub(crate) use self::elgamal_registry::DC_SPL_ELGAMAL_REGISTRY_EVENT_VERSION; /// Maximum retained SPL ElGamal registry instruction payload size. -pub(crate) use self::elgamal_registry::SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; +pub(crate) use self::elgamal_registry::DC_SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; /// Stable SPL ElGamal registry surface code. -pub(crate) use self::elgamal_registry::SPL_ELGAMAL_REGISTRY_SURFACE_CODE; +pub(crate) use self::elgamal_registry::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE; /// Canonical tracing target for the SPL ElGamal registry decoder. -pub(crate) use self::elgamal_registry::SPL_ELGAMAL_REGISTRY_TRACING_TARGET; +pub(crate) use self::elgamal_registry::DC_SPL_ELGAMAL_REGISTRY_TRACING_TARGET; +/// One parsed SPL ElGamal registry instruction. +pub(crate) use self::elgamal_registry::DcSplElGamalRegistryParsedRegistryInstruction; /// Decodes one bounded SPL ElGamal registry instruction. -pub(crate) use self::elgamal_registry::spl_elgamal_registry_decode; +pub(crate) use self::elgamal_registry::decoder_spl_elgamal_registry_decode; /// Decodes one bounded SPL ElGamal registry instruction payload. -pub(crate) use self::elgamal_registry::spl_elgamal_registry_decode_payload; +pub(crate) use self::elgamal_registry::decoder_spl_elgamal_registry_decode_payload; /// Parses one exact SPL ElGamal registry instruction. -pub(crate) use self::elgamal_registry::spl_elgamal_registry_parse; +pub(crate) use self::elgamal_registry::decoder_spl_elgamal_registry_parse; /// Maximum payload prefix retained for bounded diagnostics. -pub(crate) use self::memo::SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::memo::DC_SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; /// Current stable Memo decoded event contract version. -pub(crate) use self::memo::SPL_MEMO_EVENT_VERSION; +pub(crate) use self::memo::DC_SPL_MEMO_EVENT_VERSION; /// Maximum decoded instruction data retained as a complete Memo payload. -pub(crate) use self::memo::SPL_MEMO_MAX_PAYLOAD_BYTES; +pub(crate) use self::memo::DC_SPL_MEMO_MAX_PAYLOAD_BYTES; /// Stable protocol code shared by Memo generations. -pub(crate) use self::memo::SPL_MEMO_PROTOCOL_CODE; +pub(crate) use self::memo::DC_SPL_MEMO_PROTOCOL_CODE; /// Canonical tracing target for the SPL Memo decoder. -pub(crate) use self::memo::SPL_MEMO_TRACING_TARGET; +pub(crate) use self::memo::DC_SPL_MEMO_TRACING_TARGET; /// Stable Memo v1 surface code. -pub(crate) use self::memo::SPL_MEMO_V1_SURFACE_CODE; +pub(crate) use self::memo::DC_SPL_MEMO_V1_SURFACE_CODE; /// Stable Memo v3 surface code. -pub(crate) use self::memo::SPL_MEMO_V3_SURFACE_CODE; +pub(crate) use self::memo::DC_SPL_MEMO_V3_SURFACE_CODE; /// Stable Memo v4 surface code. -pub(crate) use self::memo::SPL_MEMO_V4_SURFACE_CODE; +pub(crate) use self::memo::DC_SPL_MEMO_V4_SURFACE_CODE; /// Decodes one bounded SPL Memo instruction. -pub(crate) use self::memo::spl_memo_decode; +pub(crate) use self::memo::decoder_spl_memo_decode; /// Maximum prefix retained in bounded classic SPL Token diagnostics. -pub(crate) use self::token::SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::token::DC_SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; /// Current stable classic SPL Token decoded event contract version. -pub(crate) use self::token::SPL_TOKEN_EVENT_VERSION; +pub(crate) use self::token::DC_SPL_TOKEN_EVENT_VERSION; /// One exact classic SPL Token instruction entry published by the official interface. -pub(crate) use self::token::SPL_TOKEN_INSTRUCTION_ENTRIES; +pub(crate) use self::token::DC_SPL_TOKEN_INSTRUCTION_ENTRIES; /// Maximum total account metas consumed by one classic SPL Token batch. -pub(crate) use self::token::SPL_TOKEN_MAX_BATCH_ACCOUNTS; +pub(crate) use self::token::DC_SPL_TOKEN_MAX_BATCH_ACCOUNTS; /// Maximum decoded sub-instructions in one classic SPL Token batch. -pub(crate) use self::token::SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; +pub(crate) use self::token::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; /// Maximum retained classic SPL Token instruction payload size. -pub(crate) use self::token::SPL_TOKEN_MAX_INSTRUCTION_BYTES; +pub(crate) use self::token::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES; /// Stable protocol and surface code for the classic SPL Token program. -pub(crate) use self::token::SPL_TOKEN_SURFACE_CODE; +pub(crate) use self::token::DC_SPL_TOKEN_SURFACE_CODE; /// Canonical tracing target for the classic SPL Token decoder. -pub(crate) use self::token::SPL_TOKEN_TRACING_TARGET; +pub(crate) use self::token::DC_SPL_TOKEN_TRACING_TARGET; /// Decodes one bounded classic SPL Token instruction. -pub(crate) use self::token::spl_token_decode; +pub(crate) use self::token::decoder_spl_token_decode; /// Returns the published entry matching one classic SPL Token tag. -pub(crate) use self::token::spl_token_entry_for_tag; +pub(crate) use self::token::decoder_spl_token_entry_for_tag; /// Returns the first byte of one retained classic SPL Token payload. -pub(crate) use self::token::spl_token_payload_tag; +pub(crate) use self::token::decoder_spl_token_payload_tag; /// Maximum prefix retained in bounded Token-2022 diagnostics. -pub(crate) use self::token_2022::SPL_TOKEN_2022_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_DIAGNOSTIC_PREFIX_BYTES; /// Current stable Token-2022 decoded event contract version. -pub(crate) use self::token_2022::SPL_TOKEN_2022_EVENT_VERSION; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_EVENT_VERSION; /// Exact top-level instruction inventory published by the resolved Token-2022 interface. -pub(crate) use self::token_2022::SPL_TOKEN_2022_INSTRUCTION_ENTRIES; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_INSTRUCTION_ENTRIES; /// Maximum total account metas consumed by one Token-2022 batch. -pub(crate) use self::token_2022::SPL_TOKEN_2022_MAX_BATCH_ACCOUNTS; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_MAX_BATCH_ACCOUNTS; /// Maximum decoded sub-instructions in one Token-2022 batch. -pub(crate) use self::token_2022::SPL_TOKEN_2022_MAX_BATCH_INSTRUCTIONS; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_MAX_BATCH_INSTRUCTIONS; /// Maximum retained Token-2022 instruction payload size. -pub(crate) use self::token_2022::SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES; /// Maximum retained UTF-8 string size for embedded Token Metadata instructions. -pub(crate) use self::token_2022::SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES; /// Stable Token-2022 surface code. -pub(crate) use self::token_2022::SPL_TOKEN_2022_SURFACE_CODE; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_SURFACE_CODE; /// Canonical tracing target for the Token-2022 decoder. -pub(crate) use self::token_2022::SPL_TOKEN_2022_TRACING_TARGET; +pub(crate) use self::token2022::DC_SPL_TOKEN2022_TRACING_TARGET; /// Decodes one bounded Token-2022 instruction. -pub(crate) use self::token_2022::spl_token_2022_decode; +pub(crate) use self::token2022::decoder_spl_token2022_decode; /// Returns the exact entry matching one Token-2022 tag. -pub(crate) use self::token_2022::spl_token_2022_entry_for_tag; +pub(crate) use self::token2022::decoder_spl_token2022_entry_for_tag; /// Returns the first byte of one retained Token-2022 payload. -pub(crate) use self::token_2022::spl_token_2022_payload_tag; +pub(crate) use self::token2022::decoder_spl_token2022_payload_tag; /// Exact decoder for the SPL Associated Token Account program. -pub use self::associated_token_account::SplAssociatedTokenAccountDecoder; +pub use self::associated_token_account::DcSplAssociatedTokenAccountDecoder; /// Exact byte length of one SPL ElGamal registry account. -pub use self::elgamal_registry::ELGAMAL_REGISTRY_ACCOUNT_LEN; +pub use self::elgamal_registry::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN; /// Parsed SPL ElGamal public-key registry account. -pub use self::elgamal_registry::ElGamalRegistryState; +pub use self::elgamal_registry::DcSplElGamalRegistryState; /// Exact decoder for the SPL ElGamal registry program. -pub use self::elgamal_registry::SplElgamalRegistryDecoder; +pub use self::elgamal_registry::DcSplElgamalRegistryDecoder; /// Parses one exact SPL ElGamal registry account. -pub use self::elgamal_registry::parse_elgamal_registry_state; +pub use self::elgamal_registry::decoder_spl_elgamal_registry_parse_elgamal_registry_state; /// Exact decoder for the three registered SPL Memo generations. -pub use self::memo::SplMemoDecoder; +pub use self::memo::DcSplMemoDecoder; /// Exact decoder for the classic SPL Token program. -pub use self::token::SplTokenDecoder; +pub use self::token::DcSplTokenDecoder; /// Exact decoder for the Token-2022 program. -pub use self::token_2022::SplToken2022Decoder; +pub use self::token2022::DcSplToken2022Decoder; /// Parsed Token-2022 Mint, Account, or Multisig state. -pub use self::token_2022::Token2022State; +pub use self::token2022::DcToken2022State; /// Exact Token-2022 base account state kind. -pub use self::token_2022::Token2022StateKind; +pub use self::token2022::DcToken2022StateKind; /// One exact Token-2022 TLV entry. -pub use self::token_2022::Token2022TlvEntry; +pub use self::token2022::DcToken2022TlvEntry; /// Parses one Token-2022 Mint, Account, or Multisig state. -pub use self::token_2022::parse_token_2022_state; +pub use self::token2022::decoder_spl_token2022_parse_token2022_state; diff --git a/kb-lib/src/decoder/spl/account_compression.rs b/kb-lib/src/decoder/spl/account_compression.rs index 2e63da5..520407a 100644 --- a/kb-lib/src/decoder/spl/account_compression.rs +++ b/kb-lib/src/decoder/spl/account_compression.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_spl_account_compression`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_spl_account_compression"; +const LEGACY_CRATE: &str = "kb_decoder_spl_account_compression"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/spl/associated_token_account.rs b/kb-lib/src/decoder/spl/associated_token_account.rs index b287479..9bab31f 100644 --- a/kb-lib/src/decoder/spl/associated_token_account.rs +++ b/kb-lib/src/decoder/spl/associated_token_account.rs @@ -8,29 +8,29 @@ mod decoder; mod wire; /// Current stable decoded event contract version. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_EVENT_VERSION; +pub(crate) use self::constants::DC_SPL_ATA_EVENT_VERSION; /// Exact instructions published by the official interface. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES; +pub(crate) use self::constants::DC_SPL_ATA_INSTRUCTION_ENTRIES; /// Maximum retained account-key text length. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNT_KEY_BYTES; +pub(crate) use self::constants::DC_SPL_ATA_MAX_ACCOUNT_KEY_BYTES; /// Maximum retained instruction account count. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNTS; +pub(crate) use self::constants::DC_SPL_ATA_MAX_ACCOUNTS; /// Maximum retained semantic diagnostic count. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_DIAGNOSTICS; +pub(crate) use self::constants::DC_SPL_ATA_MAX_DIAGNOSTICS; /// Maximum retained instruction payload size. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_INSTRUCTION_BYTES; +pub(crate) use self::constants::DC_SPL_ATA_MAX_INSTRUCTION_BYTES; /// Maximum retained transaction account-key count. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_TRANSACTION_KEYS; +pub(crate) use self::constants::DC_SPL_ATA_MAX_TRANSACTION_KEYS; /// Stable protocol and surface code for the Associated Token Account program. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE; +pub(crate) use self::constants::DC_SPL_ATA_SURFACE_CODE; /// Canonical tracing target for the Associated Token Account decoder. -pub(crate) use self::constants::SPL_ASSOCIATED_TOKEN_ACCOUNT_TRACING_TARGET; +pub(crate) use self::constants::DC_SPL_ATA_TRACING_TARGET; /// Decodes one bounded Associated Token Account instruction. -pub(crate) use self::wire::decode as spl_associated_token_account_decode; +pub(crate) use self::wire::decoder_spl_associated_token_account_decode; /// Returns the exact entry matching an Associated Token Account wire. -pub(crate) use self::wire::entry as spl_associated_token_account_entry; +pub(crate) use self::wire::decoder_spl_associated_token_account_entry; /// Reads one bounded Associated Token Account payload. -pub(crate) use self::wire::payload as spl_associated_token_account_payload; +pub(crate) use self::wire::decoder_spl_associated_token_account_payload; /// Exact decoder for the SPL Associated Token Account program. -pub use self::decoder::SplAssociatedTokenAccountDecoder; +pub use self::decoder::DcSplAssociatedTokenAccountDecoder; diff --git a/kb-lib/src/decoder/spl/associated_token_account/constants.rs b/kb-lib/src/decoder/spl/associated_token_account/constants.rs index 317abd0..527ca9f 100644 --- a/kb-lib/src/decoder/spl/associated_token_account/constants.rs +++ b/kb-lib/src/decoder/spl/associated_token_account/constants.rs @@ -4,25 +4,24 @@ //! Local constants for the `kb-lib` SPL Associated Token Account component. /// Stable protocol and surface code for the Associated Token Account program. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE: &str = "spl_associated_token_account"; +pub(crate) const DC_SPL_ATA_SURFACE_CODE: &str = "spl_associated_token_account"; /// Current stable decoded event contract version. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_EVENT_VERSION: u32 = 1; +pub(crate) const DC_SPL_ATA_EVENT_VERSION: u32 = 1; /// Maximum retained instruction payload size. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_INSTRUCTION_BYTES: usize = 64; +pub(crate) const DC_SPL_ATA_MAX_INSTRUCTION_BYTES: usize = 64; /// Maximum retained instruction account count. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNTS: usize = 64; +pub(crate) const DC_SPL_ATA_MAX_ACCOUNTS: usize = 64; /// Maximum retained transaction account-key count. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_TRANSACTION_KEYS: usize = 4_096; +pub(crate) const DC_SPL_ATA_MAX_TRANSACTION_KEYS: usize = 4_096; /// Maximum retained account-key text length. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNT_KEY_BYTES: usize = 128; +pub(crate) const DC_SPL_ATA_MAX_ACCOUNT_KEY_BYTES: usize = 128; /// Maximum retained semantic diagnostic count. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_DIAGNOSTICS: usize = 32; +pub(crate) const DC_SPL_ATA_MAX_DIAGNOSTICS: usize = 32; /// Exact instructions published by `spl-associated-token-account-interface` 2.0.0. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ +pub(crate) const DC_SPL_ATA_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ (0, "create", false), (1, "create_idempotent", false), (2, "recover_nested", false), ]; /// Canonical tracing target for the Associated Token Account decoder. -pub(crate) const SPL_ASSOCIATED_TOKEN_ACCOUNT_TRACING_TARGET: &str = - "kb-lib.decoder.spl.associated_token_account"; +pub(crate) const DC_SPL_ATA_TRACING_TARGET: &str = "kb-lib.decoder.spl.associated_token_account"; diff --git a/kb-lib/src/decoder/spl/associated_token_account/decoder.rs b/kb-lib/src/decoder/spl/associated_token_account/decoder.rs index 5f110c2..2885db7 100644 --- a/kb-lib/src/decoder/spl/associated_token_account/decoder.rs +++ b/kb-lib/src/decoder/spl/associated_token_account/decoder.rs @@ -3,9 +3,9 @@ //! Exact SPL Associated Token Account dispatch for the common decode pipeline. -const SURFACES: &[crate::DecoderSurface] = &[crate::DecoderSurface { +const SURFACES: &[crate::DcApiDecoderSurface] = &[crate::DcApiDecoderSurface { program_id: kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID, - surface_code: crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE, + surface_code: crate::DC_SPL_ATA_SURFACE_CODE, priority: 100, }]; @@ -13,9 +13,9 @@ const PROGRAM_IDS: &[&str] = &[kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID]; /// Exact decoder for the SPL Associated Token Account program. #[derive(Clone, Debug, Default)] -pub struct SplAssociatedTokenAccountDecoder; +pub struct DcSplAssociatedTokenAccountDecoder; -impl crate::ProtocolDecoder for crate::SplAssociatedTokenAccountDecoder { +impl crate::DcApiProtocolDecoder for crate::DcSplAssociatedTokenAccountDecoder { fn decoder_name(&self) -> &'static str { return "kb_decoder_spl_associated_token_account"; } @@ -30,45 +30,45 @@ impl crate::ProtocolDecoder for crate::SplAssociatedTokenAccountDecoder { fn supports_observation( &self, - observation: &crate::ProgramObservation, - ) -> crate::DecoderSupport { - return if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) { - crate::DecoderSupport::Yes + observation: &crate::MdProgramObservation, + ) -> crate::DcApiDecoderSupport { + return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + crate::DcApiDecoderSupport::Yes } else { - crate::DecoderSupport::No + crate::DcApiDecoderSupport::No }; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::InstructionDecoder for crate::SplAssociatedTokenAccountDecoder { - fn identity(&self) -> crate::DecoderIdentity { - return crate::DecoderIdentity { - name: crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE.to_string(), +impl crate::DcApiInstructionDecoder for crate::DcSplAssociatedTokenAccountDecoder { + fn identity(&self) -> crate::DcApiDecoderIdentity { + return crate::DcApiDecoderIdentity { + name: crate::DC_SPL_ATA_SURFACE_CODE.to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn surfaces(&self) -> &'static [crate::DecoderSurface] { + fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] { return SURFACES; } - fn coverage(&self) -> std::vec::Vec { - return crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES + fn coverage(&self) -> std::vec::Vec { + return crate::DC_SPL_ATA_INSTRUCTION_ENTRIES .iter() .map(|(tag, code, historical)| { - return crate::DecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE.to_string(), + crate::DC_SPL_ATA_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: (*code).to_string(), discriminator_hex: std::option::Option::Some(format!("{tag:02x}")), historical: *historical, @@ -77,40 +77,47 @@ impl crate::InstructionDecoder for crate::SplAssociatedTokenAccountDecoder { .collect(); } - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition { + fn recognize( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderRecognition { if input.program_id != kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID { - return crate::DecoderRecognition::incompatible(); + return crate::DcApiDecoderRecognition::incompatible(); } - let wire = crate::spl_associated_token_account_payload(input).ok(); + let wire = crate::decoder_spl_associated_token_account_payload(input).ok(); let entry = wire .as_ref() - .and_then(|bytes| return crate::spl_associated_token_account_entry(bytes)); - return crate::DecoderRecognition::compatible( + .and_then(|bytes| return crate::decoder_spl_associated_token_account_entry(bytes)); + return crate::DcApiDecoderRecognition::compatible( entry.is_some(), 100, - std::option::Option::Some(crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SPL_ATA_SURFACE_CODE.to_string()), entry.map(|(_, code, _)| return code.to_string()), wire.and_then(|bytes| return bytes.first().map(|tag| return format!("{tag:02x}"))), ); } - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { + fn decode( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderExecutionResult { if input.program_id != kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID { - return crate::DecoderExecutionResult::unsupported(std::option::Option::None); + return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None); } - let result = crate::spl_associated_token_account_decode(input); + let result = crate::decoder_spl_associated_token_account_decode(input); if matches!( result.status, - crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported + crate::DcApiDecoderOutcomeStatus::Failed + | crate::DcApiDecoderOutcomeStatus::Unsupported ) { tracing::error!( - target: crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_TRACING_TARGET, + target: crate::DC_SPL_ATA_TRACING_TARGET, action = "decode_failure", signature = %input.signature, slot = input.slot, instruction_path = %input.instruction_path, program_id = %input.program_id, - processor_name = crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE, + processor_name = crate::DC_SPL_ATA_SURFACE_CODE, processor_version = env!("CARGO_PKG_VERSION"), input_key = %input.replay_input_key, result_status = ?result.status, @@ -119,7 +126,7 @@ impl crate::InstructionDecoder for crate::SplAssociatedTokenAccountDecoder { ); } tracing::debug!( - target: crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_TRACING_TARGET, + target: crate::DC_SPL_ATA_TRACING_TARGET, action = "decode", signature = %input.signature, instruction_path = %input.instruction_path, @@ -180,12 +187,12 @@ mod tests { } assert_eq!(matrix["surfaceEquality"]["matrixVariantCount"], 3); assert_eq!(matrix["surfaceEquality"]["officialInterfaceVariantCount"], 3); - let compiled = crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES + let compiled = crate::DC_SPL_ATA_INSTRUCTION_ENTRIES .iter() .map(|(tag, code, _)| return (std::option::Option::Some(*tag), (*code).to_string())) .collect::>(); let declared = - crate::InstructionDecoder::coverage(&crate::SplAssociatedTokenAccountDecoder) + crate::DcApiInstructionDecoder::coverage(&crate::DcSplAssociatedTokenAccountDecoder) .iter() .map(|entry| { let tag = entry @@ -325,7 +332,7 @@ mod tests { metas: &[(std::string::String, bool, bool)], failed: bool, path: &str, - ) -> crate::CoreInstructionReplayInput { + ) -> crate::MdCoreInstructionReplayInput { use base64::Engine; // rust-rules: trait-import let keys = metas @@ -352,7 +359,7 @@ mod tests { }); }) .collect::>(); - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{path}"), "signature", 42, @@ -427,25 +434,26 @@ mod tests { #[test] fn exact_dispatch_and_coverage_are_compiled() { assert_eq!( - crate::InstructionDecoder::coverage(&crate::SplAssociatedTokenAccountDecoder).len(), + crate::DcApiInstructionDecoder::coverage(&crate::DcSplAssociatedTokenAccountDecoder) + .len(), 3 ); - let observation = crate::ProgramObservation { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(1), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string()), + let observation = crate::MdProgramObservation { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(1), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string()), discriminator_8: std::option::Option::None, data_len: 1, accounts_len: 6, failed: false, }; assert_eq!( - crate::ProtocolDecoder::supports_observation( - &crate::SplAssociatedTokenAccountDecoder, + crate::DcApiProtocolDecoder::supports_observation( + &crate::DcSplAssociatedTokenAccountDecoder, &observation, ), - crate::DecoderSupport::Yes + crate::DcApiDecoderSupport::Yes ); } @@ -454,9 +462,11 @@ mod tests { let (wire, metas) = create_fixture(kb_program_ids::SPL_TOKEN_PROGRAM_ID, false); for candidate in [wire.as_slice(), &[]] { let input = replay(candidate, metas.as_slice(), false, "0"); - let result = - crate::InstructionDecoder::decode(&crate::SplAssociatedTokenAccountDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode( + &crate::DcSplAssociatedTokenAccountDecoder, + &input, + ); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some("create") @@ -479,20 +489,22 @@ mod tests { } #[test] - fn token_2022_inner_failed_idempotent_remains_an_uncommitted_intent() { - let (wire, metas) = create_fixture(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, true); + fn token2022_inner_failed_idempotent_remains_an_uncommitted_intent() { + let (wire, metas) = create_fixture(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, true); let input = replay(wire.as_slice(), metas.as_slice(), true, "2/1"); - let result = - crate::InstructionDecoder::decode(&crate::SplAssociatedTokenAccountDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode( + &crate::DcSplAssociatedTokenAccountDecoder, + &input, + ); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!( result.observations[0].event.source_kind, - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction ); assert_eq!( result.observations[0].payload_json["addresses"]["tokenProgram"]["kind"], - "token_2022" + "token2022" ); assert_eq!(result.observations[0].payload_json["tokenProgramExtensionsDecoded"], false); } @@ -511,7 +523,7 @@ mod tests { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("invalid nested mint fixture: {error}"), }; - let token_program = match kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.parse() { + let token_program = match kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.parse() { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("invalid token program fixture: {error}"), }; @@ -527,9 +539,11 @@ mod tests { .map(|meta| return (meta.pubkey.to_string(), meta.is_signer, meta.is_writable)) .collect::>(); let input = replay(instruction.data.as_slice(), metas.as_slice(), false, "1/0"); - let result = - crate::InstructionDecoder::decode(&crate::SplAssociatedTokenAccountDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode( + &crate::DcSplAssociatedTokenAccountDecoder, + &input, + ); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let addresses = &result.observations[0].payload_json["addresses"]; assert_eq!(addresses["ownerMint"], owner_mint.to_string()); assert_eq!(addresses["nestedMint"], nested_mint.to_string()); @@ -553,9 +567,11 @@ mod tests { metas[0].1 = false; metas.push(("SysvarC1ock11111111111111111111111111111111".to_string(), false, false)); let input = replay(wire.as_slice(), metas.as_slice(), false, "0"); - let result = - crate::InstructionDecoder::decode(&crate::SplAssociatedTokenAccountDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode( + &crate::DcSplAssociatedTokenAccountDecoder, + &input, + ); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); let diagnostics = result.observations[0].payload_json["semanticDiagnostics"].as_array(); let diagnostics = match diagnostics { std::option::Option::Some(value) => value, @@ -572,9 +588,11 @@ mod tests { metas.truncate(3); let input = replay(wire.as_slice(), metas.as_slice(), false, "0"); - let result = - crate::InstructionDecoder::decode(&crate::SplAssociatedTokenAccountDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode( + &crate::DcSplAssociatedTokenAccountDecoder, + &input, + ); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!( result.observations[0].payload_json["semanticDiagnostics"] .as_array() @@ -589,9 +607,11 @@ mod tests { let (_, metas) = create_fixture(kb_program_ids::SPL_TOKEN_PROGRAM_ID, false); for wire in [std::vec![9], std::vec![0, 0]] { let input = replay(wire.as_slice(), metas.as_slice(), false, "0"); - let result = - crate::InstructionDecoder::decode(&crate::SplAssociatedTokenAccountDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = crate::DcApiInstructionDecoder::decode( + &crate::DcSplAssociatedTokenAccountDecoder, + &input, + ); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert_eq!(result.observations.len(), 0); assert_eq!(result.diagnostics.len(), 1); assert!(result.diagnostics[0].message.len() < 256); diff --git a/kb-lib/src/decoder/spl/associated_token_account/wire.rs b/kb-lib/src/decoder/spl/associated_token_account/wire.rs index 6e5283b..abf3e1e 100644 --- a/kb-lib/src/decoder/spl/associated_token_account/wire.rs +++ b/kb-lib/src/decoder/spl/associated_token_account/wire.rs @@ -16,21 +16,23 @@ struct Account { source: serde_json::Value, } -pub(crate) fn entry(bytes: &[u8]) -> std::option::Option<(u8, &'static str, bool)> { +pub(crate) fn decoder_spl_associated_token_account_entry( + bytes: &[u8], +) -> std::option::Option<(u8, &'static str, bool)> { if bytes.is_empty() { return std::option::Option::Some((0, "create", true)); } if bytes.len() != 1 { return std::option::Option::None; } - return crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES + return crate::DC_SPL_ATA_INSTRUCTION_ENTRIES .iter() .copied() .find(|(tag, _, _)| return *tag == bytes[0]); } -pub(crate) fn payload( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_spl_associated_token_account_payload( + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result> { let value = match input.instruction_payload_json.as_ref() { std::option::Option::Some(value) => value, @@ -61,7 +63,7 @@ pub(crate) fn payload( ))); }, }; - if bytes.len() > crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_INSTRUCTION_BYTES { + if bytes.len() > crate::DC_SPL_ATA_MAX_INSTRUCTION_BYTES { return std::result::Result::Err(kb_core::Error::invalid_state( "ATA decoded payload exceeds 64 bytes", )); @@ -69,14 +71,16 @@ pub(crate) fn payload( return std::result::Result::Ok(bytes); } -pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { - let bytes = match crate::spl_associated_token_account_payload(input) { +pub(crate) fn decoder_spl_associated_token_account_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes = match crate::decoder_spl_associated_token_account_payload(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { return failed(std::option::Option::None, "ata_payload_unavailable", error.to_string()); }, }; - let instruction = match crate::spl_associated_token_account_entry(bytes.as_slice()) { + let instruction = match crate::decoder_spl_associated_token_account_entry(bytes.as_slice()) { std::option::Option::Some(value) => value, std::option::Option::None => { let code = if bytes.len() > 1 { @@ -106,37 +110,33 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode let addresses = addresses(instruction.1, accounts.as_slice()); let hash = hash(bytes.as_slice()); let committed = !input.transaction_failed; - let confidence = crate::DecoderConfidence::ManualExact; - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(input.instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode( - crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE.to_string(), - ), - surface_code: crate::SurfaceCode( - crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE.to_string(), - ), - event_code: crate::EventCode(format!( + let confidence = crate::MdDecoderConfidence::ManualExact; + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(input.instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode(crate::DC_SPL_ATA_SURFACE_CODE.to_string()), + surface_code: crate::MdSurfaceCode(crate::DC_SPL_ATA_SURFACE_CODE.to_string()), + event_code: crate::MdEventCode(format!( "{}.{}", - crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE, + crate::DC_SPL_ATA_SURFACE_CODE, instruction.1 )), - event_name: crate::EventName(instruction.1.to_string()), - event_family: crate::EventFamily::Lifecycle, + event_name: crate::MdEventName(instruction.1.to_string()), + event_family: crate::MdEventFamily::Lifecycle, source_kind: if input.instruction_path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction }, confidence, }; - let observation = crate::DecodedObservation { + let observation = crate::DcApiDecodedObservation { event_key: format!("ata:{}:0", instruction.1), event, payload_json: serde_json::json!({ - "eventVersion": crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_EVENT_VERSION, + "eventVersion": crate::DC_SPL_ATA_EVENT_VERSION, "programId": input.program_id, "instruction": instruction.1, "wireTag": instruction.0, @@ -161,8 +161,8 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: committed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, confidence, evidence: std::vec![ "spl_associated_token_account_interface_2_0_0_and_processor_audit".to_string(), @@ -170,15 +170,17 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode ], }, }; - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some(instruction.1.to_string()), observations: std::vec![observation], diagnostics: std::vec::Vec::new(), }; } -fn accounts(input: &crate::CoreInstructionReplayInput) -> kb_core::Result> { +fn accounts( + input: &crate::MdCoreInstructionReplayInput, +) -> kb_core::Result> { let instruction_accounts = match input.instruction_accounts_json.as_array() { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -195,12 +197,12 @@ fn accounts(input: &crate::CoreInstructionReplayInput) -> kb_core::Result crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNTS { + if instruction_accounts.len() > crate::DC_SPL_ATA_MAX_ACCOUNTS { return std::result::Result::Err(kb_core::Error::invalid_state( "ATA instruction account count exceeds 64", )); } - if keys.len() > crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_TRANSACTION_KEYS { + if keys.len() > crate::DC_SPL_ATA_MAX_TRANSACTION_KEYS { return std::result::Result::Err(kb_core::Error::invalid_state( "ATA transaction account key count exceeds 4096", )); @@ -217,8 +219,7 @@ fn accounts(input: &crate::CoreInstructionReplayInput) -> kb_core::Result + if !value.is_empty() && value.len() <= crate::DC_SPL_ATA_MAX_ACCOUNT_KEY_BYTES => { value }, @@ -351,7 +352,7 @@ fn diagnostics(code: &str, accounts: &[Account]) -> serde_json::Value { let token_position = if code == "recover_nested" { 6 } else { 5 }; if accounts.get(token_position).is_some_and(|account| { return account.key != kb_program_ids::SPL_TOKEN_PROGRAM_ID - && account.key != kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID; + && account.key != kb_program_ids::SPL_TOKEN2022_PROGRAM_ID; }) { values.push(serde_json::json!({"code":"unsupported_token_program","observed":accounts.get(token_position).map(|value| return value.key.clone())})); } @@ -363,7 +364,7 @@ fn diagnostics(code: &str, accounts: &[Account]) -> serde_json::Value { values .push(serde_json::json!({"code":"system_program_mismatch","observed":accounts[4].key})); } - values.truncate(crate::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_DIAGNOSTICS); + values.truncate(crate::DC_SPL_ATA_MAX_DIAGNOSTICS); return serde_json::Value::Array(values); } @@ -422,8 +423,8 @@ fn token_kind(token: std::option::Option<&str>) -> serde_json::Value { std::option::Option::Some(kb_program_ids::SPL_TOKEN_PROGRAM_ID) => { serde_json::json!({"programId":kb_program_ids::SPL_TOKEN_PROGRAM_ID,"kind":"spl_token_classic","supported":true}) }, - std::option::Option::Some(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID) => { - serde_json::json!({"programId":kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID,"kind":"token_2022","supported":true}) + std::option::Option::Some(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID) => { + serde_json::json!({"programId":kb_program_ids::SPL_TOKEN2022_PROGRAM_ID,"kind":"token2022","supported":true}) }, std::option::Option::Some(value) => { serde_json::json!({"programId":value,"kind":"unsupported","supported":false}) @@ -438,12 +439,12 @@ fn failed( entry: std::option::Option<&str>, code: &str, message: std::string::String, -) -> crate::DecoderExecutionResult { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, +) -> crate::DcApiDecoderExecutionResult { + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: entry.map(|value| return value.to_string()), observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: code.to_string(), message, retriable: false diff --git a/kb-lib/src/decoder/spl/elgamal_registry.rs b/kb-lib/src/decoder/spl/elgamal_registry.rs index ef115c3..8cbd164 100644 --- a/kb-lib/src/decoder/spl/elgamal_registry.rs +++ b/kb-lib/src/decoder/spl/elgamal_registry.rs @@ -9,27 +9,27 @@ mod state; mod wire; /// Current stable SPL ElGamal registry event contract version. -pub(crate) use self::constants::SPL_ELGAMAL_REGISTRY_EVENT_VERSION; +pub(crate) use self::constants::DC_SPL_ELGAMAL_REGISTRY_EVENT_VERSION; /// Maximum retained SPL ElGamal registry instruction payload size. -pub(crate) use self::constants::SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; +pub(crate) use self::constants::DC_SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; /// Stable SPL ElGamal registry surface code. -pub(crate) use self::constants::SPL_ELGAMAL_REGISTRY_SURFACE_CODE; +pub(crate) use self::constants::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE; /// Canonical tracing target for the SPL ElGamal registry decoder. -pub(crate) use self::constants::SPL_ELGAMAL_REGISTRY_TRACING_TARGET; +pub(crate) use self::constants::DC_SPL_ELGAMAL_REGISTRY_TRACING_TARGET; /// One parsed SPL ElGamal registry instruction. -pub(crate) use self::wire::ParsedRegistryInstruction; +pub(crate) use self::wire::DcSplElGamalRegistryParsedRegistryInstruction; /// Decodes one bounded SPL ElGamal registry instruction. -pub(crate) use self::wire::spl_elgamal_registry_decode; +pub(crate) use self::wire::decoder_spl_elgamal_registry_decode; /// Decodes one bounded SPL ElGamal registry instruction payload. -pub(crate) use self::wire::spl_elgamal_registry_decode_payload; +pub(crate) use self::wire::decoder_spl_elgamal_registry_decode_payload; /// Parses one exact SPL ElGamal registry instruction. -pub(crate) use self::wire::spl_elgamal_registry_parse; +pub(crate) use self::wire::decoder_spl_elgamal_registry_parse; /// Exact decoder for the SPL ElGamal registry program. -pub use self::decoder::SplElgamalRegistryDecoder; +pub use self::decoder::DcSplElgamalRegistryDecoder; /// Exact byte length of one SPL ElGamal registry account. -pub use self::state::ELGAMAL_REGISTRY_ACCOUNT_LEN; +pub use self::state::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN; /// Parsed SPL ElGamal public-key registry account. -pub use self::state::ElGamalRegistryState; +pub use self::state::DcSplElGamalRegistryState; /// Parses one exact SPL ElGamal registry account. -pub use self::state::parse_elgamal_registry_state; +pub use self::state::decoder_spl_elgamal_registry_parse_elgamal_registry_state; diff --git a/kb-lib/src/decoder/spl/elgamal_registry/constants.rs b/kb-lib/src/decoder/spl/elgamal_registry/constants.rs index eaee3ba..7c5442e 100644 --- a/kb-lib/src/decoder/spl/elgamal_registry/constants.rs +++ b/kb-lib/src/decoder/spl/elgamal_registry/constants.rs @@ -3,9 +3,10 @@ //! Constants for the SPL ElGamal registry decoder. -pub(crate) const SPL_ELGAMAL_REGISTRY_SURFACE_CODE: &str = "spl_elgamal_registry"; -pub(crate) const SPL_ELGAMAL_REGISTRY_EVENT_VERSION: u32 = 1; -pub(crate) const SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES: usize = 16; +pub(crate) const DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE: &str = "spl_elgamal_registry"; +pub(crate) const DC_SPL_ELGAMAL_REGISTRY_EVENT_VERSION: u32 = 1; +pub(crate) const DC_SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES: usize = 16; /// Canonical tracing target for this crate. -pub(crate) const SPL_ELGAMAL_REGISTRY_TRACING_TARGET: &str = "kb-lib.decoder.spl.elgamal_registry"; +pub(crate) const DC_SPL_ELGAMAL_REGISTRY_TRACING_TARGET: &str = + "kb-lib.decoder.spl.elgamal_registry"; diff --git a/kb-lib/src/decoder/spl/elgamal_registry/decoder.rs b/kb-lib/src/decoder/spl/elgamal_registry/decoder.rs index a8657bc..efd8212 100644 --- a/kb-lib/src/decoder/spl/elgamal_registry/decoder.rs +++ b/kb-lib/src/decoder/spl/elgamal_registry/decoder.rs @@ -3,19 +3,19 @@ //! Exact dispatch for the SPL ElGamal registry program. -const SURFACES: &[crate::DecoderSurface] = &[crate::DecoderSurface { - program_id: kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, - surface_code: crate::SPL_ELGAMAL_REGISTRY_SURFACE_CODE, +const SURFACES: &[crate::DcApiDecoderSurface] = &[crate::DcApiDecoderSurface { + program_id: kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, + surface_code: crate::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE, priority: 100, }]; -const PROGRAM_IDS: &[&str] = &[kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID]; +const PROGRAM_IDS: &[&str] = &[kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID]; /// Decoder for the dedicated Token-2022 ElGamal public-key registry program. #[derive(Clone, Debug, Default)] -pub struct SplElgamalRegistryDecoder; +pub struct DcSplElgamalRegistryDecoder; -impl crate::ProtocolDecoder for crate::SplElgamalRegistryDecoder { +impl crate::DcApiProtocolDecoder for crate::DcSplElgamalRegistryDecoder { fn decoder_name(&self) -> &'static str { return "kb_decoder_spl_elgamal_registry"; } @@ -30,46 +30,46 @@ impl crate::ProtocolDecoder for crate::SplElgamalRegistryDecoder { fn supports_observation( &self, - observation: &crate::ProgramObservation, - ) -> crate::DecoderSupport { - return if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) { - crate::DecoderSupport::Yes + observation: &crate::MdProgramObservation, + ) -> crate::DcApiDecoderSupport { + return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + crate::DcApiDecoderSupport::Yes } else { - crate::DecoderSupport::No + crate::DcApiDecoderSupport::No }; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::InstructionDecoder for crate::SplElgamalRegistryDecoder { - fn identity(&self) -> crate::DecoderIdentity { - return crate::DecoderIdentity { +impl crate::DcApiInstructionDecoder for crate::DcSplElgamalRegistryDecoder { + fn identity(&self) -> crate::DcApiDecoderIdentity { + return crate::DcApiDecoderIdentity { name: "spl_elgamal_registry".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn surfaces(&self) -> &'static [crate::DecoderSurface] { + fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] { return SURFACES; } - fn coverage(&self) -> std::vec::Vec { + fn coverage(&self) -> std::vec::Vec { return [(0_u8, "create_registry"), (1_u8, "update_registry")] .into_iter() .map(|(tag, code)| { - return crate::DecoderCoverageDeclaration { - program_id: kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID + return crate::DcApiDecoderCoverageDeclaration { + program_id: kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID .to_string(), surface_code: std::option::Option::Some( - crate::SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string(), + crate::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: code.to_string(), discriminator_hex: std::option::Option::Some(format!("{tag:02x}")), historical: false, @@ -78,9 +78,12 @@ impl crate::InstructionDecoder for crate::SplElgamalRegistryDecoder { .collect(); } - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition { - if input.program_id != kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID { - return crate::DecoderRecognition::incompatible(); + fn recognize( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderRecognition { + if input.program_id != kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID { + return crate::DcApiDecoderRecognition::incompatible(); } let entry = input .instruction_payload_json @@ -99,26 +102,30 @@ impl crate::InstructionDecoder for crate::SplElgamalRegistryDecoder { _ => std::option::Option::None, }; }); - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( entry.is_some(), 100, - std::option::Option::Some(crate::SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string()), entry, std::option::Option::None, ); } - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { - if input.program_id != kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID { - return crate::DecoderExecutionResult::unsupported(std::option::Option::None); + fn decode( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderExecutionResult { + if input.program_id != kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID { + return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None); } - let result = crate::spl_elgamal_registry_decode(input); + let result = crate::decoder_spl_elgamal_registry_decode(input); if matches!( result.status, - crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported + crate::DcApiDecoderOutcomeStatus::Failed + | crate::DcApiDecoderOutcomeStatus::Unsupported ) { tracing::error!( - target: crate::SPL_ELGAMAL_REGISTRY_TRACING_TARGET, + target: crate::DC_SPL_ELGAMAL_REGISTRY_TRACING_TARGET, action = "decode_failure", signature = %input.signature, slot = input.slot, @@ -135,7 +142,7 @@ impl crate::InstructionDecoder for crate::SplElgamalRegistryDecoder { ); } tracing::debug!( - target: crate::SPL_ELGAMAL_REGISTRY_TRACING_TARGET, + target: crate::DC_SPL_ELGAMAL_REGISTRY_TRACING_TARGET, action = "decode", signature = %input.signature, instruction_path = %input.instruction_path, @@ -158,8 +165,8 @@ mod tests { payload: &[u8], failed: bool, path: &str, - ) -> crate::CoreInstructionReplayInput { - let result = crate::CoreInstructionReplayInput::new( + ) -> crate::MdCoreInstructionReplayInput { + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{path}"), "signature", 42, @@ -192,14 +199,14 @@ mod tests { fn exact_program_boundary_and_interface_id_are_preserved() { assert_eq!( spl_elgamal_registry_interface::id().to_string(), - kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID + kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID ); - let decoder = crate::SplElgamalRegistryDecoder; - assert_eq!(crate::InstructionDecoder::coverage(&decoder).len(), 2); - let foreign = input(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, &[0, 1], false, "0"); + let decoder = crate::DcSplElgamalRegistryDecoder; + assert_eq!(crate::DcApiInstructionDecoder::coverage(&decoder).len(), 2); + let foreign = input(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, &[0, 1], false, "0"); assert_eq!( - crate::InstructionDecoder::decode(&decoder, &foreign).status, - crate::DecoderOutcomeStatus::Unsupported + crate::DcApiInstructionDecoder::decode(&decoder, &foreign).status, + crate::DcApiDecoderOutcomeStatus::Unsupported ); } @@ -211,14 +218,14 @@ mod tests { (1_u8, "update_registry", 0_i8, false, "2"), ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, &[tag, offset as u8], failed, path, ); let result = - crate::InstructionDecoder::decode(&crate::SplElgamalRegistryDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + crate::DcApiInstructionDecoder::decode(&crate::DcSplElgamalRegistryDecoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some(code)); assert_eq!( result.observations[0].payload_json["proofInstructionOffset"], @@ -232,14 +239,14 @@ mod tests { fn malformed_unknown_and_suffixed_wire_fail_closed() { for payload in [std::vec::Vec::new(), vec![0], vec![2, 0], vec![0, 1, 2]] { let input = input( - kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, payload.as_slice(), false, "0", ); let result = - crate::InstructionDecoder::decode(&crate::SplElgamalRegistryDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + crate::DcApiInstructionDecoder::decode(&crate::DcSplElgamalRegistryDecoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert!(result.observations.is_empty()); } } diff --git a/kb-lib/src/decoder/spl/elgamal_registry/state.rs b/kb-lib/src/decoder/spl/elgamal_registry/state.rs index 1fe9d64..73f10f5 100644 --- a/kb-lib/src/decoder/spl/elgamal_registry/state.rs +++ b/kb-lib/src/decoder/spl/elgamal_registry/state.rs @@ -6,11 +6,11 @@ use base64::Engine; // rust-rules: trait-import /// Exact byte length of one SPL ElGamal registry account. -pub const ELGAMAL_REGISTRY_ACCOUNT_LEN: usize = 64; +pub const DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN: usize = 64; /// Public state retained by one SPL ElGamal registry account. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct ElGamalRegistryState { +pub struct DcSplElGamalRegistryState { /// Wallet address associated with this registry. pub owner: String, /// Exact 32-byte ElGamal public key encoded as standard base64. @@ -20,16 +20,16 @@ pub struct ElGamalRegistryState { } /// Parse one exact SPL ElGamal registry account. -pub fn parse_elgamal_registry_state( +pub fn decoder_spl_elgamal_registry_parse_elgamal_registry_state( data: &[u8], -) -> std::result::Result { - if data.len() != ELGAMAL_REGISTRY_ACCOUNT_LEN { +) -> std::result::Result { + if data.len() != DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN { return std::result::Result::Err(format!( - "SPL ElGamal registry account requires exactly {ELGAMAL_REGISTRY_ACCOUNT_LEN} bytes; received {}", + "SPL ElGamal registry account requires exactly {DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN} bytes; received {}", data.len() )); } - return std::result::Result::Ok(ElGamalRegistryState { + return std::result::Result::Ok(DcSplElGamalRegistryState { owner: bs58::encode(&data[..32]).into_string(), elgamal_pubkey_base64: base64::engine::general_purpose::STANDARD.encode(&data[32..64]), wire_hex: lower_hex(data), @@ -50,10 +50,10 @@ mod tests { #[test] fn exact_registry_state_preserves_owner_key_and_wire() { - let mut data = [0u8; crate::ELGAMAL_REGISTRY_ACCOUNT_LEN]; + let mut data = [0u8; crate::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN]; data[..32].fill(7); data[32..].fill(9); - let parsed = crate::parse_elgamal_registry_state(&data); + let parsed = crate::decoder_spl_elgamal_registry_parse_elgamal_registry_state(&data); assert_eq!( parsed.as_ref().map(|state| return state.owner.clone()), std::result::Result::Ok(bs58::encode([7u8; 32]).into_string()) @@ -70,7 +70,11 @@ mod tests { #[test] fn registry_state_rejects_every_non_exact_length() { - assert!(crate::parse_elgamal_registry_state(&[0; 63]).is_err()); - assert!(crate::parse_elgamal_registry_state(&[0; 65]).is_err()); + assert!( + crate::decoder_spl_elgamal_registry_parse_elgamal_registry_state(&[0; 63]).is_err() + ); + assert!( + crate::decoder_spl_elgamal_registry_parse_elgamal_registry_state(&[0; 65]).is_err() + ); } } diff --git a/kb-lib/src/decoder/spl/elgamal_registry/wire.rs b/kb-lib/src/decoder/spl/elgamal_registry/wire.rs index 5d2671b..2067c6f 100644 --- a/kb-lib/src/decoder/spl/elgamal_registry/wire.rs +++ b/kb-lib/src/decoder/spl/elgamal_registry/wire.rs @@ -7,14 +7,14 @@ use base64::Engine; // rust-rules: trait-import use sha2::Digest; // rust-rules: trait-import #[derive(Clone, Debug)] -pub(crate) struct ParsedRegistryInstruction { +pub(crate) struct DcSplElGamalRegistryParsedRegistryInstruction { pub(crate) code: &'static str, pub(crate) tag: u8, pub(crate) proof_instruction_offset: i8, } -pub(crate) fn spl_elgamal_registry_decode_payload( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_spl_elgamal_registry_decode_payload( + input: &crate::MdCoreInstructionReplayInput, ) -> std::result::Result, std::string::String> { let payload = match input.instruction_payload_json.as_ref() { std::option::Option::Some(value) => value, @@ -45,18 +45,19 @@ pub(crate) fn spl_elgamal_registry_decode_payload( )); }, }; - if bytes.len() > crate::SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES { + if bytes.len() > crate::DC_SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES { return std::result::Result::Err(format!( "ElGamal registry payload exceeds {} bytes", - crate::SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES + crate::DC_SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES )); } return std::result::Result::Ok(bytes); } -pub(crate) fn spl_elgamal_registry_parse( +pub(crate) fn decoder_spl_elgamal_registry_parse( bytes: &[u8], -) -> std::result::Result { +) -> std::result::Result +{ if bytes.len() != 2 { return std::result::Result::Err(format!( "ElGamal registry instruction requires exactly 2 bytes; received {}", @@ -68,24 +69,24 @@ pub(crate) fn spl_elgamal_registry_parse( 1 => "update_registry", tag => return std::result::Result::Err(format!("unknown ElGamal registry tag {tag}")), }; - return std::result::Result::Ok(crate::ParsedRegistryInstruction { + return std::result::Result::Ok(crate::DcSplElGamalRegistryParsedRegistryInstruction { code, tag: bytes[0], proof_instruction_offset: bytes[1] as i8, }); } -pub(crate) fn spl_elgamal_registry_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { - let bytes = match crate::spl_elgamal_registry_decode_payload(input) { +pub(crate) fn decoder_spl_elgamal_registry_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { + let bytes = match crate::decoder_spl_elgamal_registry_decode_payload(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(message) => { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: std::option::Option::None, observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: "elgamal_registry_payload_invalid".to_string(), message, retriable: false, @@ -93,11 +94,11 @@ pub(crate) fn spl_elgamal_registry_decode( }; }, }; - let parsed = match crate::spl_elgamal_registry_parse(bytes.as_slice()) { + let parsed = match crate::decoder_spl_elgamal_registry_parse(bytes.as_slice()) { std::result::Result::Ok(value) => value, std::result::Result::Err(message) => { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: bytes.first().and_then(|tag| { return match tag { 0 => std::option::Option::Some("create_registry".to_string()), @@ -106,7 +107,7 @@ pub(crate) fn spl_elgamal_registry_decode( }; }), observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: "elgamal_registry_wire_invalid".to_string(), message, retriable: false, @@ -116,32 +117,34 @@ pub(crate) fn spl_elgamal_registry_decode( }; let committed = !input.transaction_failed; let wire_hash = hash(bytes.as_slice()); - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(input.instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode(crate::SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string()), - surface_code: crate::SurfaceCode(crate::SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string()), - event_code: crate::EventCode(format!( + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(input.instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode( + crate::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string(), + ), + surface_code: crate::MdSurfaceCode(crate::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE.to_string()), + event_code: crate::MdEventCode(format!( "{}.{}", - crate::SPL_ELGAMAL_REGISTRY_SURFACE_CODE, + crate::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE, parsed.code )), - event_name: crate::EventName(parsed.code.to_string()), - event_family: crate::EventFamily::Admin, + event_name: crate::MdEventName(parsed.code.to_string()), + event_family: crate::MdEventFamily::Admin, source_kind: if input.instruction_path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction }, - confidence: crate::DecoderConfidence::ManualExact, + confidence: crate::MdDecoderConfidence::ManualExact, }; - let observation = crate::DecodedObservation { + let observation = crate::DcApiDecodedObservation { event_key: format!("elgamal_registry:{}:0", parsed.code), event, payload_json: serde_json::json!({ - "eventVersion": crate::SPL_ELGAMAL_REGISTRY_EVENT_VERSION, + "eventVersion": crate::DC_SPL_ELGAMAL_REGISTRY_EVENT_VERSION, "instruction": parsed.code, "wireTag": parsed.tag, "proofInstructionOffset": parsed.proof_instruction_offset, @@ -158,8 +161,8 @@ pub(crate) fn spl_elgamal_registry_decode( "complete": true, }, "programBoundary": { - "registryProgramId": kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, - "token2022ProgramId": kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + "registryProgramId": kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, + "token2022ProgramId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, "zkProofProgramId": kb_program_ids::ZK_ELGAMAL_PROOF_PROGRAM_ID, "proofDecodedHere": false, } @@ -167,9 +170,9 @@ pub(crate) fn spl_elgamal_registry_decode( transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: committed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec![ "spl_elgamal_registry_interface_0_2_1_registry_instruction_unpack".to_string(), format!("wire_tag:{}", parsed.tag), @@ -177,8 +180,8 @@ pub(crate) fn spl_elgamal_registry_decode( ], }, }; - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some(parsed.code.to_string()), observations: std::vec![observation], diagnostics: std::vec::Vec::new(), diff --git a/kb-lib/src/decoder/spl/memo.rs b/kb-lib/src/decoder/spl/memo.rs index d8d0758..81bd068 100644 --- a/kb-lib/src/decoder/spl/memo.rs +++ b/kb-lib/src/decoder/spl/memo.rs @@ -8,23 +8,23 @@ mod decoder; mod payload; /// Maximum payload prefix retained for bounded diagnostics. -pub(crate) use self::constants::SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::constants::DC_SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; /// Current stable Memo decoded event contract version. -pub(crate) use self::constants::SPL_MEMO_EVENT_VERSION; +pub(crate) use self::constants::DC_SPL_MEMO_EVENT_VERSION; /// Maximum decoded instruction data retained as a complete Memo payload. -pub(crate) use self::constants::SPL_MEMO_MAX_PAYLOAD_BYTES; +pub(crate) use self::constants::DC_SPL_MEMO_MAX_PAYLOAD_BYTES; /// Stable protocol code shared by Memo generations. -pub(crate) use self::constants::SPL_MEMO_PROTOCOL_CODE; +pub(crate) use self::constants::DC_SPL_MEMO_PROTOCOL_CODE; /// Canonical tracing target for the SPL Memo decoder. -pub(crate) use self::constants::SPL_MEMO_TRACING_TARGET; +pub(crate) use self::constants::DC_SPL_MEMO_TRACING_TARGET; /// Stable Memo v1 surface code. -pub(crate) use self::constants::SPL_MEMO_V1_SURFACE_CODE; +pub(crate) use self::constants::DC_SPL_MEMO_V1_SURFACE_CODE; /// Stable Memo v3 surface code. -pub(crate) use self::constants::SPL_MEMO_V3_SURFACE_CODE; +pub(crate) use self::constants::DC_SPL_MEMO_V3_SURFACE_CODE; /// Stable Memo v4 surface code. -pub(crate) use self::constants::SPL_MEMO_V4_SURFACE_CODE; +pub(crate) use self::constants::DC_SPL_MEMO_V4_SURFACE_CODE; /// Decodes one bounded SPL Memo instruction. -pub(crate) use self::payload::decode as spl_memo_decode; +pub(crate) use self::payload::decoder_spl_memo_decode; /// Exact decoder for the three registered SPL Memo generations. -pub use self::decoder::SplMemoDecoder; +pub use self::decoder::DcSplMemoDecoder; diff --git a/kb-lib/src/decoder/spl/memo/constants.rs b/kb-lib/src/decoder/spl/memo/constants.rs index 4ca6148..c64ecc6 100644 --- a/kb-lib/src/decoder/spl/memo/constants.rs +++ b/kb-lib/src/decoder/spl/memo/constants.rs @@ -4,18 +4,18 @@ //! Local constants for the `kb-lib` SPL Memo component. Program identifiers live in `kb_program_ids`. /// Stable protocol code shared by Memo generations. -pub(crate) const SPL_MEMO_PROTOCOL_CODE: &str = "spl_memo"; +pub(crate) const DC_SPL_MEMO_PROTOCOL_CODE: &str = "spl_memo"; /// Stable Memo v1 surface code. -pub(crate) const SPL_MEMO_V1_SURFACE_CODE: &str = "spl_memo_v1"; +pub(crate) const DC_SPL_MEMO_V1_SURFACE_CODE: &str = "spl_memo_v1"; /// Stable Memo v3 surface code. -pub(crate) const SPL_MEMO_V3_SURFACE_CODE: &str = "spl_memo_v3"; +pub(crate) const DC_SPL_MEMO_V3_SURFACE_CODE: &str = "spl_memo_v3"; /// Stable Memo v4 surface code. -pub(crate) const SPL_MEMO_V4_SURFACE_CODE: &str = "spl_memo_v4"; +pub(crate) const DC_SPL_MEMO_V4_SURFACE_CODE: &str = "spl_memo_v4"; /// Maximum decoded instruction data retained as a complete Memo payload. -pub(crate) const SPL_MEMO_MAX_PAYLOAD_BYTES: usize = 4_096; +pub(crate) const DC_SPL_MEMO_MAX_PAYLOAD_BYTES: usize = 4_096; /// Maximum payload prefix retained for bounded diagnostics. -pub(crate) const SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES: usize = 32; +pub(crate) const DC_SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES: usize = 32; /// Current stable Memo decoded event contract version. -pub(crate) const SPL_MEMO_EVENT_VERSION: u32 = 1; +pub(crate) const DC_SPL_MEMO_EVENT_VERSION: u32 = 1; /// Canonical tracing target for this crate. -pub(crate) const SPL_MEMO_TRACING_TARGET: &str = "kb-lib.decoder.spl.memo"; +pub(crate) const DC_SPL_MEMO_TRACING_TARGET: &str = "kb-lib.decoder.spl.memo"; diff --git a/kb-lib/src/decoder/spl/memo/decoder.rs b/kb-lib/src/decoder/spl/memo/decoder.rs index 8d84f8c..d2b167e 100644 --- a/kb-lib/src/decoder/spl/memo/decoder.rs +++ b/kb-lib/src/decoder/spl/memo/decoder.rs @@ -3,20 +3,20 @@ //! Exact SPL Memo v1, v3 and v4 dispatch for the common decode pipeline. -const MEMO_SURFACES: &[crate::DecoderSurface] = &[ - crate::DecoderSurface { +const MEMO_SURFACES: &[crate::DcApiDecoderSurface] = &[ + crate::DcApiDecoderSurface { program_id: kb_program_ids::SPL_MEMO_V1_PROGRAM_ID, - surface_code: crate::SPL_MEMO_V1_SURFACE_CODE, + surface_code: crate::DC_SPL_MEMO_V1_SURFACE_CODE, priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::SPL_MEMO_V3_PROGRAM_ID, - surface_code: crate::SPL_MEMO_V3_SURFACE_CODE, + surface_code: crate::DC_SPL_MEMO_V3_SURFACE_CODE, priority: 100, }, - crate::DecoderSurface { + crate::DcApiDecoderSurface { program_id: kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, - surface_code: crate::SPL_MEMO_V4_SURFACE_CODE, + surface_code: crate::DC_SPL_MEMO_V4_SURFACE_CODE, priority: 100, }, ]; @@ -29,9 +29,9 @@ const LEGACY_PROGRAM_IDS: &[&str] = &[ /// Exact decoder for the three registered SPL Memo generations. #[derive(Clone, Debug, Default)] -pub struct SplMemoDecoder; +pub struct DcSplMemoDecoder; -impl crate::ProtocolDecoder for crate::SplMemoDecoder { +impl crate::DcApiProtocolDecoder for crate::DcSplMemoDecoder { fn decoder_name(&self) -> &'static str { return "kb_decoder_spl_memo"; } @@ -46,42 +46,42 @@ impl crate::ProtocolDecoder for crate::SplMemoDecoder { fn supports_observation( &self, - observation: &crate::ProgramObservation, - ) -> crate::DecoderSupport { - if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) { - return crate::DecoderSupport::Yes; + observation: &crate::MdProgramObservation, + ) -> crate::DcApiDecoderSupport { + if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + return crate::DcApiDecoderSupport::Yes; } - return crate::DecoderSupport::No; + return crate::DcApiDecoderSupport::No; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::InstructionDecoder for crate::SplMemoDecoder { - fn identity(&self) -> crate::DecoderIdentity { - return crate::DecoderIdentity { +impl crate::DcApiInstructionDecoder for crate::DcSplMemoDecoder { + fn identity(&self) -> crate::DcApiDecoderIdentity { + return crate::DcApiDecoderIdentity { name: "spl_memo".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn surfaces(&self) -> &'static [crate::DecoderSurface] { + fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] { return MEMO_SURFACES; } - fn coverage(&self) -> std::vec::Vec { + fn coverage(&self) -> std::vec::Vec { return MEMO_SURFACES .iter() .map(|surface| { - return crate::DecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: surface.program_id.to_string(), surface_code: std::option::Option::Some(surface.surface_code.to_string()), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: "add_memo".to_string(), discriminator_hex: std::option::Option::None, historical: surface.program_id != kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, @@ -90,15 +90,18 @@ impl crate::InstructionDecoder for crate::SplMemoDecoder { .collect(); } - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition { + fn recognize( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderRecognition { let surface = MEMO_SURFACES .iter() .find(|surface| return surface.program_id == input.program_id); let surface = match surface { std::option::Option::Some(value) => value, - std::option::Option::None => return crate::DecoderRecognition::incompatible(), + std::option::Option::None => return crate::DcApiDecoderRecognition::incompatible(), }; - return crate::DecoderRecognition::compatible( + return crate::DcApiDecoderRecognition::compatible( true, surface.priority, std::option::Option::Some(surface.surface_code.to_string()), @@ -107,17 +110,21 @@ impl crate::InstructionDecoder for crate::SplMemoDecoder { ); } - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { + fn decode( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderExecutionResult { if !LEGACY_PROGRAM_IDS.contains(&input.program_id.as_str()) { - return crate::DecoderExecutionResult::unsupported(std::option::Option::None); + return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None); } - let result = crate::spl_memo_decode(input); + let result = crate::decoder_spl_memo_decode(input); if matches!( result.status, - crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported + crate::DcApiDecoderOutcomeStatus::Failed + | crate::DcApiDecoderOutcomeStatus::Unsupported ) { tracing::error!( - target: crate::SPL_MEMO_TRACING_TARGET, + target: crate::DC_SPL_MEMO_TRACING_TARGET, action = "decode_failure", signature = %input.signature, slot = input.slot, @@ -134,7 +141,7 @@ impl crate::InstructionDecoder for crate::SplMemoDecoder { ); } tracing::debug!( - target: crate::SPL_MEMO_TRACING_TARGET, + target: crate::DC_SPL_MEMO_TRACING_TARGET, action = "decode", signature = %input.signature, instruction_path = %input.instruction_path, @@ -159,8 +166,8 @@ mod tests { keys: serde_json::Value, failed: bool, path: &str, - ) -> crate::CoreInstructionReplayInput { - let result = crate::CoreInstructionReplayInput::new( + ) -> crate::MdCoreInstructionReplayInput { + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{path}"), "signature", 42, @@ -198,13 +205,13 @@ mod tests { #[test] fn exact_support_and_interface_ids_cover_all_generations() { - let decoder = crate::SplMemoDecoder; + let decoder = crate::DcSplMemoDecoder; assert_eq!(spl_memo_interface::v1::ID.to_string(), kb_program_ids::SPL_MEMO_V1_PROGRAM_ID); assert_eq!(spl_memo_interface::v3::ID.to_string(), kb_program_ids::SPL_MEMO_V3_PROGRAM_ID); assert_eq!(spl_memo_interface::v4::ID.to_string(), kb_program_ids::SPL_MEMO_V4_PROGRAM_ID); - assert_eq!(crate::InstructionDecoder::surfaces(&decoder).len(), 3); + assert_eq!(crate::DcApiInstructionDecoder::surfaces(&decoder).len(), 3); assert!( - crate::InstructionDecoder::coverage(&decoder) + crate::DcApiInstructionDecoder::coverage(&decoder) .iter() .all(|entry| return entry.entry_code == "add_memo") ); @@ -225,8 +232,8 @@ mod tests { false, path, ); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.observations[0].payload_json["payloadLengthBytes"], serde_json::json!(payload.len()) @@ -235,9 +242,9 @@ mod tests { assert_eq!( result.observations[0].event.source_kind, if path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction } ); } @@ -254,7 +261,7 @@ mod tests { false, "0", ); - let v1_result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &v1); + let v1_result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &v1); assert_eq!(v1_result.observations[0].event.event_name.0, "add_memo"); assert_eq!( v1_result.observations[0].payload_json["signerValidation"]["status"], @@ -264,7 +271,7 @@ mod tests { [kb_program_ids::SPL_MEMO_V3_PROGRAM_ID, kb_program_ids::SPL_MEMO_V4_PROGRAM_ID] { let input = input(program_id, b"signed", accounts.clone(), keys.clone(), false, "0"); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input); assert_eq!(result.observations[0].event.event_name.0, "invalid_memo_attempt"); assert_eq!( result.observations[0].payload_json["signerValidation"]["status"], @@ -284,7 +291,8 @@ mod tests { true, "0", ); - let invalid_result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &invalid); + let invalid_result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &invalid); assert_eq!(invalid_result.observations[0].event.event_name.0, "invalid_memo_attempt"); assert_eq!( invalid_result.observations[0].payload_json["utf8Validation"]["status"], @@ -300,7 +308,7 @@ mod tests { "0", ); let failed_result = - crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &valid_failed); + crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &valid_failed); assert_eq!(failed_result.observations[0].event.event_name.0, "memo_intent"); assert!(!failed_result.observations[0].observation_committed); assert_eq!( @@ -322,7 +330,7 @@ mod tests { ]); let input = input(kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, b"ordered", accounts, keys, false, "0"); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input); assert_eq!(result.observations[0].payload_json["accounts"][0]["pubkey"], "first"); assert_eq!(result.observations[0].payload_json["accounts"][0]["writable"], true); assert_eq!(result.observations[0].payload_json["accounts"][2]["pubkey"], "first"); @@ -346,7 +354,7 @@ mod tests { false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input); assert_eq!( result.observations[0].payload_json["payloadSha256"], "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" @@ -355,7 +363,7 @@ mod tests { #[test] fn payload_bound_accepts_limit_and_rejects_oversize_and_malformed_base64() { - let at_limit = std::vec![b'x'; crate::SPL_MEMO_MAX_PAYLOAD_BYTES]; + let at_limit = std::vec![b'x'; crate::DC_SPL_MEMO_MAX_PAYLOAD_BYTES]; let cinput = input( kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, at_limit.as_slice(), @@ -364,9 +372,9 @@ mod tests { false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &cinput); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); - let oversize = std::vec![b'x'; crate::SPL_MEMO_MAX_PAYLOAD_BYTES + 1]; + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &cinput); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); + let oversize = std::vec![b'x'; crate::DC_SPL_MEMO_MAX_PAYLOAD_BYTES + 1]; let cinput = input( kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, oversize.as_slice(), @@ -375,8 +383,8 @@ mod tests { false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &cinput); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &cinput); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); let mut malformed = input( kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, b"valid", @@ -387,8 +395,8 @@ mod tests { ); malformed.instruction_payload_json = std::option::Option::Some(serde_json::json!({"dataBase64":"%%%"})); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &malformed); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &malformed); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert!(result.observations.is_empty()); } @@ -402,10 +410,11 @@ mod tests { false, "0", ); - let recognition = crate::InstructionDecoder::recognize(&crate::SplMemoDecoder, &input); + let recognition = + crate::DcApiInstructionDecoder::recognize(&crate::DcSplMemoDecoder, &input); assert!(!recognition.compatible); - let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported); assert!(result.observations.is_empty()); } diff --git a/kb-lib/src/decoder/spl/memo/payload.rs b/kb-lib/src/decoder/spl/memo/payload.rs index 1eef8e4..93ac339 100644 --- a/kb-lib/src/decoder/spl/memo/payload.rs +++ b/kb-lib/src/decoder/spl/memo/payload.rs @@ -37,9 +37,9 @@ impl MemoGeneration { fn surface_code(self) -> &'static str { return match self { - Self::V1 => crate::SPL_MEMO_V1_SURFACE_CODE, - Self::V3 => crate::SPL_MEMO_V3_SURFACE_CODE, - Self::V4 => crate::SPL_MEMO_V4_SURFACE_CODE, + Self::V1 => crate::DC_SPL_MEMO_V1_SURFACE_CODE, + Self::V3 => crate::DC_SPL_MEMO_V3_SURFACE_CODE, + Self::V4 => crate::DC_SPL_MEMO_V4_SURFACE_CODE, }; } @@ -55,11 +55,13 @@ struct ResolvedAccounts { missing_signers: std::vec::Vec, } -pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { +pub(crate) fn decoder_spl_memo_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { let generation = match MemoGeneration::from_program_id(input.program_id.as_str()) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::DecoderExecutionResult::unsupported(std::option::Option::None); + return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None); }, }; let bytes = match decode_payload(input) { @@ -117,28 +119,28 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode std::vec::Vec::new() }; let payload_hash = hash(bytes.as_slice()); - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(input.instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode(crate::SPL_MEMO_PROTOCOL_CODE.to_string()), - surface_code: crate::SurfaceCode(generation.surface_code().to_string()), - event_code: crate::EventCode(format!("{}.{event_name}", generation.surface_code())), - event_name: crate::EventName(event_name.to_string()), - event_family: crate::EventFamily::Audit, + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(input.instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode(crate::DC_SPL_MEMO_PROTOCOL_CODE.to_string()), + surface_code: crate::MdSurfaceCode(generation.surface_code().to_string()), + event_code: crate::MdEventCode(format!("{}.{event_name}", generation.surface_code())), + event_name: crate::MdEventName(event_name.to_string()), + event_family: crate::MdEventFamily::Audit, source_kind: if input.instruction_path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction }, - confidence: crate::DecoderConfidence::ManualExact, + confidence: crate::MdDecoderConfidence::ManualExact, }; - let observation = crate::DecodedObservation { + let observation = crate::DcApiDecodedObservation { event_key: "memo:0".to_string(), event, payload_json: serde_json::json!({ - "eventVersion": crate::SPL_MEMO_EVENT_VERSION, + "eventVersion": crate::DC_SPL_MEMO_EVENT_VERSION, "generation": generation.code(), "programId": input.program_id, "instructionPath": input.instruction_path, @@ -176,9 +178,9 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: !input.transaction_failed && structurally_valid, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec![ "spl_memo_exact_raw_instruction_data".to_string(), format!("payload_sha256:{payload_hash}"), @@ -186,15 +188,17 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode ], }, }; - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some("add_memo".to_string()), observations: std::vec![observation], diagnostics: std::vec::Vec::new(), }; } -fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result> { +fn decode_payload( + input: &crate::MdCoreInstructionReplayInput, +) -> kb_core::Result> { let payload = match input.instruction_payload_json.as_ref() { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -211,7 +215,7 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< )); }, }; - let maximum_encoded = crate::SPL_MEMO_MAX_PAYLOAD_BYTES + let maximum_encoded = crate::DC_SPL_MEMO_MAX_PAYLOAD_BYTES .saturating_mul(4) .saturating_div(3) .saturating_add(4); @@ -228,17 +232,17 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< ))); }, }; - if decoded.len() > crate::SPL_MEMO_MAX_PAYLOAD_BYTES { + if decoded.len() > crate::DC_SPL_MEMO_MAX_PAYLOAD_BYTES { return std::result::Result::Err(kb_core::Error::invalid_state(format!( "Memo payload exceeds {} decoded bytes", - crate::SPL_MEMO_MAX_PAYLOAD_BYTES + crate::DC_SPL_MEMO_MAX_PAYLOAD_BYTES ))); } return std::result::Result::Ok(decoded); } fn resolve_accounts( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result { let instruction_accounts = match input.instruction_accounts_json.as_array() { std::option::Option::Some(value) => value, @@ -349,7 +353,7 @@ fn hash(bytes: &[u8]) -> std::string::String { } fn hex_prefix(bytes: &[u8]) -> std::string::String { - let length = std::cmp::min(bytes.len(), crate::SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES); + let length = std::cmp::min(bytes.len(), crate::DC_SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES); let mut output = std::string::String::with_capacity(length.saturating_mul(2)); for byte in &bytes[..length] { output.push_str(format!("{byte:02x}").as_str()); @@ -357,12 +361,12 @@ fn hex_prefix(bytes: &[u8]) -> std::string::String { return output; } -fn failed(code: &str, message: std::string::String) -> crate::DecoderExecutionResult { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, +fn failed(code: &str, message: std::string::String) -> crate::DcApiDecoderExecutionResult { + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: std::option::Option::Some("add_memo".to_string()), observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: code.to_string(), message, retriable: false, diff --git a/kb-lib/src/decoder/spl/noop.rs b/kb-lib/src/decoder/spl/noop.rs index 6730263..48c8360 100644 --- a/kb-lib/src/decoder/spl/noop.rs +++ b/kb-lib/src/decoder/spl/noop.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_spl_noop`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_spl_noop"; +const LEGACY_CRATE: &str = "kb_decoder_spl_noop"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/spl/single_pool.rs b/kb-lib/src/decoder/spl/single_pool.rs index 48cfd2a..5438ec3 100644 --- a/kb-lib/src/decoder/spl/single_pool.rs +++ b/kb-lib/src/decoder/spl/single_pool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_spl_single_pool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_spl_single_pool"; +const LEGACY_CRATE: &str = "kb_decoder_spl_single_pool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/spl/stake_pool.rs b/kb-lib/src/decoder/spl/stake_pool.rs index e0b82b3..3888d2d 100644 --- a/kb-lib/src/decoder/spl/stake_pool.rs +++ b/kb-lib/src/decoder/spl/stake_pool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_spl_stake_pool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_spl_stake_pool"; +const LEGACY_CRATE: &str = "kb_decoder_spl_stake_pool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/spl/token.rs b/kb-lib/src/decoder/spl/token.rs index 2fd64af..3a22eca 100644 --- a/kb-lib/src/decoder/spl/token.rs +++ b/kb-lib/src/decoder/spl/token.rs @@ -8,27 +8,27 @@ mod decoder; mod wire; /// Maximum prefix retained in bounded diagnostics. -pub(crate) use self::constants::SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::constants::DC_SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; /// Current stable decoded event contract version. -pub(crate) use self::constants::SPL_TOKEN_EVENT_VERSION; +pub(crate) use self::constants::DC_SPL_TOKEN_EVENT_VERSION; /// One exact instruction entry published by `spl-token-interface` 3.0.0. -pub(crate) use self::constants::SPL_TOKEN_INSTRUCTION_ENTRIES; +pub(crate) use self::constants::DC_SPL_TOKEN_INSTRUCTION_ENTRIES; /// Maximum total account metas consumed by one batch. -pub(crate) use self::constants::SPL_TOKEN_MAX_BATCH_ACCOUNTS; +pub(crate) use self::constants::DC_SPL_TOKEN_MAX_BATCH_ACCOUNTS; /// Maximum decoded sub-instructions in one batch. -pub(crate) use self::constants::SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; +pub(crate) use self::constants::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; /// Maximum retained instruction payload size. -pub(crate) use self::constants::SPL_TOKEN_MAX_INSTRUCTION_BYTES; +pub(crate) use self::constants::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES; /// Stable protocol and surface code for the classic SPL Token program. -pub(crate) use self::constants::SPL_TOKEN_SURFACE_CODE; +pub(crate) use self::constants::DC_SPL_TOKEN_SURFACE_CODE; /// Canonical tracing target for the classic SPL Token decoder. -pub(crate) use self::constants::SPL_TOKEN_TRACING_TARGET; +pub(crate) use self::constants::DC_SPL_TOKEN_TRACING_TARGET; /// Decodes one bounded classic SPL Token instruction. -pub(crate) use self::wire::decode as spl_token_decode; +pub(crate) use self::wire::decoder_spl_token_decode; /// Returns the published entry matching one classic SPL Token tag. -pub(crate) use self::wire::entry_for_tag as spl_token_entry_for_tag; +pub(crate) use self::wire::decoder_spl_token_entry_for_tag; /// Returns the first byte of one retained classic SPL Token payload. -pub(crate) use self::wire::payload_tag as spl_token_payload_tag; +pub(crate) use self::wire::decoder_spl_token_payload_tag; /// Exact decoder for the classic SPL Token program. -pub use self::decoder::SplTokenDecoder; +pub use self::decoder::DcSplTokenDecoder; diff --git a/kb-lib/src/decoder/spl/token/constants.rs b/kb-lib/src/decoder/spl/token/constants.rs index 2fd5169..65e20e0 100644 --- a/kb-lib/src/decoder/spl/token/constants.rs +++ b/kb-lib/src/decoder/spl/token/constants.rs @@ -4,19 +4,19 @@ //! Local constants for the `kb-lib` SPL Token component. Program identifiers live in `kb_program_ids`. /// Stable protocol and surface code for the classic SPL Token program. -pub(crate) const SPL_TOKEN_SURFACE_CODE: &str = "spl_token"; +pub(crate) const DC_SPL_TOKEN_SURFACE_CODE: &str = "spl_token"; /// Current stable decoded event contract version. -pub(crate) const SPL_TOKEN_EVENT_VERSION: u32 = 1; +pub(crate) const DC_SPL_TOKEN_EVENT_VERSION: u32 = 1; /// Maximum retained instruction payload size. -pub(crate) const SPL_TOKEN_MAX_INSTRUCTION_BYTES: usize = 16_384; +pub(crate) const DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES: usize = 16_384; /// Maximum prefix retained in diagnostics. -pub(crate) const SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES: usize = 32; +pub(crate) const DC_SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES: usize = 32; /// Maximum decoded sub-instructions in one batch. -pub(crate) const SPL_TOKEN_MAX_BATCH_INSTRUCTIONS: usize = 64; +pub(crate) const DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS: usize = 64; /// Maximum total account metas consumed by one batch. -pub(crate) const SPL_TOKEN_MAX_BATCH_ACCOUNTS: usize = 512; +pub(crate) const DC_SPL_TOKEN_MAX_BATCH_ACCOUNTS: usize = 512; /// One exact instruction entry published by `spl-token-interface` 3.0.0. -pub(crate) const SPL_TOKEN_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ +pub(crate) const DC_SPL_TOKEN_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ (0, "initialize_mint", true), (1, "initialize_account", true), (2, "initialize_multisig", true), @@ -47,4 +47,4 @@ pub(crate) const SPL_TOKEN_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ (255, "batch", false), ]; /// Canonical tracing target for this crate. -pub(crate) const SPL_TOKEN_TRACING_TARGET: &str = "kb-lib.decoder.spl.token"; +pub(crate) const DC_SPL_TOKEN_TRACING_TARGET: &str = "kb-lib.decoder.spl.token"; diff --git a/kb-lib/src/decoder/spl/token/decoder.rs b/kb-lib/src/decoder/spl/token/decoder.rs index 856b137..a0a02f6 100644 --- a/kb-lib/src/decoder/spl/token/decoder.rs +++ b/kb-lib/src/decoder/spl/token/decoder.rs @@ -3,9 +3,9 @@ //! Exact classic SPL Token dispatch for the common decode pipeline. -const TOKEN_SURFACES: &[crate::DecoderSurface] = &[crate::DecoderSurface { +const TOKEN_SURFACES: &[crate::DcApiDecoderSurface] = &[crate::DcApiDecoderSurface { program_id: kb_program_ids::SPL_TOKEN_PROGRAM_ID, - surface_code: crate::SPL_TOKEN_SURFACE_CODE, + surface_code: crate::DC_SPL_TOKEN_SURFACE_CODE, priority: 100, }]; @@ -13,9 +13,9 @@ const PROGRAM_IDS: &[&str] = &[kb_program_ids::SPL_TOKEN_PROGRAM_ID]; /// Exact decoder for the classic SPL Token program. #[derive(Clone, Debug, Default)] -pub struct SplTokenDecoder; +pub struct DcSplTokenDecoder; -impl crate::ProtocolDecoder for crate::SplTokenDecoder { +impl crate::DcApiProtocolDecoder for crate::DcSplTokenDecoder { fn decoder_name(&self) -> &'static str { return "kb_decoder_spl_token"; } @@ -30,45 +30,45 @@ impl crate::ProtocolDecoder for crate::SplTokenDecoder { fn supports_observation( &self, - observation: &crate::ProgramObservation, - ) -> crate::DecoderSupport { - return if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) { - crate::DecoderSupport::Yes + observation: &crate::MdProgramObservation, + ) -> crate::DcApiDecoderSupport { + return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + crate::DcApiDecoderSupport::Yes } else { - crate::DecoderSupport::No + crate::DcApiDecoderSupport::No }; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::InstructionDecoder for crate::SplTokenDecoder { - fn identity(&self) -> crate::DecoderIdentity { - return crate::DecoderIdentity { +impl crate::DcApiInstructionDecoder for crate::DcSplTokenDecoder { + fn identity(&self) -> crate::DcApiDecoderIdentity { + return crate::DcApiDecoderIdentity { name: "spl_token".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn surfaces(&self) -> &'static [crate::DecoderSurface] { + fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] { return TOKEN_SURFACES; } - fn coverage(&self) -> std::vec::Vec { - return crate::SPL_TOKEN_INSTRUCTION_ENTRIES + fn coverage(&self) -> std::vec::Vec { + return crate::DC_SPL_TOKEN_INSTRUCTION_ENTRIES .iter() .map(|(tag, code, historical)| { - return crate::DecoderCoverageDeclaration { + return crate::DcApiDecoderCoverageDeclaration { program_id: kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SPL_TOKEN_SURFACE_CODE.to_string(), + crate::DC_SPL_TOKEN_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: (*code).to_string(), discriminator_hex: std::option::Option::Some(format!("{tag:02x}")), historical: *historical, @@ -77,32 +77,39 @@ impl crate::InstructionDecoder for crate::SplTokenDecoder { .collect(); } - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition { + fn recognize( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderRecognition { if input.program_id != kb_program_ids::SPL_TOKEN_PROGRAM_ID { - return crate::DecoderRecognition::incompatible(); + return crate::DcApiDecoderRecognition::incompatible(); } - let tag = crate::spl_token_payload_tag(input); - let entry = tag.and_then(crate::spl_token_entry_for_tag); - return crate::DecoderRecognition::compatible( + let tag = crate::decoder_spl_token_payload_tag(input); + let entry = tag.and_then(crate::decoder_spl_token_entry_for_tag); + return crate::DcApiDecoderRecognition::compatible( entry.is_some(), 100, - std::option::Option::Some(crate::SPL_TOKEN_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SPL_TOKEN_SURFACE_CODE.to_string()), entry.map(|(_, code, _)| return code.to_string()), tag.map(|value| return format!("{value:02x}")), ); } - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { + fn decode( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderExecutionResult { if input.program_id != kb_program_ids::SPL_TOKEN_PROGRAM_ID { - return crate::DecoderExecutionResult::unsupported(std::option::Option::None); + return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None); } - let result = crate::spl_token_decode(input); + let result = crate::decoder_spl_token_decode(input); if matches!( result.status, - crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported + crate::DcApiDecoderOutcomeStatus::Failed + | crate::DcApiDecoderOutcomeStatus::Unsupported ) { tracing::error!( - target: crate::SPL_TOKEN_TRACING_TARGET, + target: crate::DC_SPL_TOKEN_TRACING_TARGET, action = "decode_failure", signature = %input.signature, slot = input.slot, @@ -118,7 +125,7 @@ impl crate::InstructionDecoder for crate::SplTokenDecoder { ); } tracing::debug!( - target: crate::SPL_TOKEN_TRACING_TARGET, + target: crate::DC_SPL_TOKEN_TRACING_TARGET, action = "decode", signature = %input.signature, instruction_path = %input.instruction_path, @@ -142,8 +149,8 @@ mod tests { keys: serde_json::Value, failed: bool, path: &str, - ) -> crate::CoreInstructionReplayInput { - let result = crate::CoreInstructionReplayInput::new( + ) -> crate::MdCoreInstructionReplayInput { + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{path}"), "signature", 42, @@ -219,21 +226,21 @@ mod tests { #[test] fn exact_support_program_id_and_interface_match() { assert_eq!(spl_token_interface::ID.to_string(), kb_program_ids::SPL_TOKEN_PROGRAM_ID); - let decoder = crate::SplTokenDecoder; - assert_eq!(crate::InstructionDecoder::surfaces(&decoder).len(), 1); - let observation = crate::ProgramObservation { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(1), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()), + let decoder = crate::DcSplTokenDecoder; + assert_eq!(crate::DcApiInstructionDecoder::surfaces(&decoder).len(), 1); + let observation = crate::MdProgramObservation { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(1), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()), discriminator_8: std::option::Option::None, data_len: 1, accounts_len: 0, failed: false, }; assert_eq!( - crate::ProtocolDecoder::supports_observation(&decoder, &observation), - crate::DecoderSupport::Yes + crate::DcApiProtocolDecoder::supports_observation(&decoder, &observation), + crate::DcApiDecoderSupport::Yes ); } @@ -257,12 +264,12 @@ mod tests { ); }) .collect::>(); - let compiled_entries = crate::SPL_TOKEN_INSTRUCTION_ENTRIES + let compiled_entries = crate::DC_SPL_TOKEN_INSTRUCTION_ENTRIES .iter() .map(|(tag, code, _)| return (*tag, *code)) .collect::>(); assert_eq!(matrix_entries, compiled_entries); - assert_eq!(crate::InstructionDecoder::coverage(&crate::SplTokenDecoder).len(), 28); + assert_eq!(crate::DcApiInstructionDecoder::coverage(&crate::DcSplTokenDecoder).len(), 28); } #[test] @@ -324,7 +331,7 @@ mod tests { #[test] fn every_published_tag_decodes_and_matches_official_unpack() { - for (tag, code, _) in crate::SPL_TOKEN_INSTRUCTION_ENTRIES { + for (tag, code, _) in crate::DC_SPL_TOKEN_INSTRUCTION_ENTRIES { let wire = minimal_wire(*tag); let official = spl_token_interface::instruction::TokenInstruction::unpack(&wire); assert!(official.is_ok(), "official unpack rejected tag {tag}"); @@ -336,8 +343,8 @@ mod tests { false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some(*code)); } } @@ -364,8 +371,8 @@ mod tests { true, "2/1", ); - let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert!(!result.observations[0].observation_committed); assert_eq!( result.observations[0].payload_json["parameters"]["amountRaw"], @@ -374,7 +381,7 @@ mod tests { assert_eq!(result.observations[0].payload_json["inference"]["mintInvented"], false); assert_eq!( result.observations[0].event.source_kind, - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction ); } @@ -390,8 +397,9 @@ mod tests { false, "0", ); - let suffix_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &suffix); - assert_eq!(suffix_result.status, crate::DecoderOutcomeStatus::Decoded); + let suffix_result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &suffix); + assert_eq!(suffix_result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(suffix_result.observations[0].payload_json["wire"]["suffixLengthBytes"], 2); for wire in [std::vec::Vec::new(), std::vec![3, 1], std::vec![24, 0xff], std::vec![255]] { let input = input( @@ -402,8 +410,8 @@ mod tests { false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert!(result.observations.is_empty()); } let unknown = input( @@ -414,8 +422,8 @@ mod tests { false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &unknown); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &unknown); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported); assert!(!result.diagnostics.is_empty()); } @@ -432,8 +440,8 @@ mod tests { false, "4/2", ); - let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &cinput); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &cinput); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.observations.len(), 3); assert_eq!(result.observations[1].event.instruction_path.0, "4/2/batch/0"); assert_eq!(result.observations[2].event.instruction_path.0, "4/2/batch/1"); @@ -446,8 +454,9 @@ mod tests { false, "0", ); - let nested_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &nested); - assert_eq!(nested_result.status, crate::DecoderOutcomeStatus::Failed); + let nested_result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &nested); + assert_eq!(nested_result.status, crate::DcApiDecoderOutcomeStatus::Failed); } #[test] @@ -471,7 +480,8 @@ mod tests { false, "0", ); - let simple_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &simple); + let simple_result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &simple); assert_eq!(simple_result.observations[0].payload_json["authority"]["form"], "single"); let mut multisig_accounts = simple_accounts.as_array().cloned().unwrap_or_default(); multisig_accounts @@ -490,7 +500,8 @@ mod tests { false, "0", ); - let multisig_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &multisig); + let multisig_result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &multisig); assert_eq!(multisig_result.observations[0].payload_json["authority"]["form"], "multisig"); assert_eq!( multisig_result.observations[0].payload_json["authority"]["statefulMultisigValidation"], diff --git a/kb-lib/src/decoder/spl/token/wire.rs b/kb-lib/src/decoder/spl/token/wire.rs index e408de2..27bbfef 100644 --- a/kb-lib/src/decoder/spl/token/wire.rs +++ b/kb-lib/src/decoder/spl/token/wire.rs @@ -24,19 +24,25 @@ struct ResolvedAccount { source: serde_json::Value, } -pub(crate) fn entry_for_tag(tag: u8) -> std::option::Option<(u8, &'static str, bool)> { - return crate::SPL_TOKEN_INSTRUCTION_ENTRIES +pub(crate) fn decoder_spl_token_entry_for_tag( + tag: u8, +) -> std::option::Option<(u8, &'static str, bool)> { + return crate::DC_SPL_TOKEN_INSTRUCTION_ENTRIES .iter() .copied() .find(|(candidate, _, _)| return *candidate == tag); } -pub(crate) fn payload_tag(input: &crate::CoreInstructionReplayInput) -> std::option::Option { +pub(crate) fn decoder_spl_token_payload_tag( + input: &crate::MdCoreInstructionReplayInput, +) -> std::option::Option { let bytes = decode_payload(input).ok(); return bytes.and_then(|value| return value.first().copied()); } -pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { +pub(crate) fn decoder_spl_token_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { let bytes = match decode_payload(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { @@ -57,14 +63,14 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode ); }, }; - let entry = match crate::spl_token_entry_for_tag(tag) { + let entry = match crate::decoder_spl_token_entry_for_tag(tag) { std::option::Option::Some(value) => value, std::option::Option::None => { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Unsupported, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Unsupported, recognized_entry_code: std::option::Option::None, observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: "unknown_token_instruction_tag".to_string(), message: format!( "unknown classic SPL Token tag {tag}; payloadPrefixHex={}", @@ -132,15 +138,17 @@ pub(crate) fn decode(input: &crate::CoreInstructionReplayInput) -> crate::Decode ); let mut observations = std::vec![parent]; observations.extend(batch_children); - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some(parsed.code.to_string()), observations, diagnostics: std::vec::Vec::new(), }; } -fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result> { +fn decode_payload( + input: &crate::MdCoreInstructionReplayInput, +) -> kb_core::Result> { let payload = match input.instruction_payload_json.as_ref() { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -157,7 +165,7 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< )); }, }; - let maximum_encoded = crate::SPL_TOKEN_MAX_INSTRUCTION_BYTES + let maximum_encoded = crate::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES .saturating_mul(4) .saturating_div(3) .saturating_add(4); @@ -174,10 +182,10 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< ))); }, }; - if decoded.len() > crate::SPL_TOKEN_MAX_INSTRUCTION_BYTES { + if decoded.len() > crate::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES { return std::result::Result::Err(kb_core::Error::invalid_state(format!( "classic SPL Token payload exceeds {} decoded bytes", - crate::SPL_TOKEN_MAX_INSTRUCTION_BYTES + crate::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES ))); } return std::result::Result::Ok(decoded); @@ -193,7 +201,7 @@ fn parse_instruction( return std::result::Result::Err("empty instruction".to_string()); }, }; - let code = match crate::spl_token_entry_for_tag(tag) { + let code = match crate::decoder_spl_token_entry_for_tag(tag) { std::option::Option::Some((_, value, _)) => value, std::option::Option::None => { return std::result::Result::Err(format!("unknown instruction tag {tag}")); @@ -452,7 +460,7 @@ fn one_parameter(field: &str, value: serde_json::Value) -> serde_json::Value { } fn resolve_accounts( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result> { let instruction_accounts = match input.instruction_accounts_json.as_array() { std::option::Option::Some(value) => value, @@ -757,7 +765,7 @@ fn valid_account_count(code: &str, count: usize) -> bool { #[allow(clippy::too_many_arguments)] fn observation( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, code: &str, tag: u8, parameters: serde_json::Value, @@ -769,31 +777,31 @@ fn observation( committed: bool, event_key: std::string::String, instruction_path: std::string::String, - family: crate::EventFamily, -) -> crate::DecodedObservation { + family: crate::MdEventFamily, +) -> crate::DcApiDecodedObservation { let wire_hash = hash(wire); - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode(crate::SPL_TOKEN_SURFACE_CODE.to_string()), - surface_code: crate::SurfaceCode(crate::SPL_TOKEN_SURFACE_CODE.to_string()), - event_code: crate::EventCode(format!("{}.{}", crate::SPL_TOKEN_SURFACE_CODE, code)), - event_name: crate::EventName(code.to_string()), + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode(crate::DC_SPL_TOKEN_SURFACE_CODE.to_string()), + surface_code: crate::MdSurfaceCode(crate::DC_SPL_TOKEN_SURFACE_CODE.to_string()), + event_code: crate::MdEventCode(format!("{}.{}", crate::DC_SPL_TOKEN_SURFACE_CODE, code)), + event_name: crate::MdEventName(code.to_string()), event_family: family, source_kind: if input.instruction_path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction }, - confidence: crate::DecoderConfidence::ManualExact, + confidence: crate::MdDecoderConfidence::ManualExact, }; - return crate::DecodedObservation { + return crate::DcApiDecodedObservation { event_key, event, payload_json: serde_json::json!({ - "eventVersion": crate::SPL_TOKEN_EVENT_VERSION, + "eventVersion": crate::DC_SPL_TOKEN_EVENT_VERSION, "programId": input.program_id, "instruction": code, "wireTag": tag, @@ -826,9 +834,9 @@ fn observation( transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: committed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec![ "spl_token_interface_3_0_0_wire_audit".to_string(), format!("wire_tag:{tag}"), @@ -839,11 +847,11 @@ fn observation( } fn batch_observations( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], accounts: &[ResolvedAccount], ) -> std::result::Result< - (std::vec::Vec, serde_json::Value), + (std::vec::Vec, serde_json::Value), std::string::String, > { if bytes.len() == 1 { @@ -855,10 +863,10 @@ fn batch_observations( let mut observations = std::vec::Vec::new(); let mut manifest = std::vec::Vec::new(); while cursor < bytes.len() { - if index >= crate::SPL_TOKEN_MAX_BATCH_INSTRUCTIONS { + if index >= crate::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS { return std::result::Result::Err(format!( "Batch exceeds {} sub-instructions", - crate::SPL_TOKEN_MAX_BATCH_INSTRUCTIONS + crate::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS )); } let account_count = match bytes.get(cursor).copied() { @@ -889,7 +897,7 @@ fn batch_observations( }, }; let account_end = account_cursor.saturating_add(account_count); - if account_end > crate::SPL_TOKEN_MAX_BATCH_ACCOUNTS || account_end > accounts.len() { + if account_end > crate::DC_SPL_TOKEN_MAX_BATCH_ACCOUNTS || account_end > accounts.len() { return std::result::Result::Err(format!( "Batch entry {index} account slice exceeds provided accounts or bound" )); @@ -947,19 +955,19 @@ fn batch_observations( )); } -fn event_family(code: &str) -> crate::EventFamily { +fn event_family(code: &str) -> crate::MdEventFamily { return match code { "set_authority" | "initialize_multisig" | "initialize_multisig2" => { - crate::EventFamily::Admin + crate::MdEventFamily::Admin }, "initialize_mint" | "initialize_mint2" | "mint_to" | "mint_to_checked" => { - crate::EventFamily::TokenMint + crate::MdEventFamily::TokenMint }, - "burn" | "burn_checked" => crate::EventFamily::TokenBurn, + "burn" | "burn_checked" => crate::MdEventFamily::TokenBurn, "batch" | "get_account_data_size" | "amount_to_ui_amount" | "ui_amount_to_amount" => { - crate::EventFamily::Audit + crate::MdEventFamily::Audit }, - _ => crate::EventFamily::TokenAccount, + _ => crate::MdEventFamily::TokenAccount, }; } @@ -973,7 +981,7 @@ fn hash(bytes: &[u8]) -> std::string::String { } fn hex_prefix(bytes: &[u8]) -> std::string::String { - let length = std::cmp::min(bytes.len(), crate::SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES); + let length = std::cmp::min(bytes.len(), crate::DC_SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES); let mut output = std::string::String::with_capacity(length.saturating_mul(2)); for byte in &bytes[..length] { output.push_str(format!("{byte:02x}").as_str()); @@ -985,12 +993,12 @@ fn failed( entry_code: std::option::Option<&str>, code: &str, message: std::string::String, -) -> crate::DecoderExecutionResult { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, +) -> crate::DcApiDecoderExecutionResult { + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: entry_code.map(str::to_string), observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: code.to_string(), message, retriable: false, diff --git a/kb-lib/src/decoder/spl/token_2022.rs b/kb-lib/src/decoder/spl/token2022.rs similarity index 50% rename from kb-lib/src/decoder/spl/token_2022.rs rename to kb-lib/src/decoder/spl/token2022.rs index 7a50e46..ba7b28e 100644 --- a/kb-lib/src/decoder/spl/token_2022.rs +++ b/kb-lib/src/decoder/spl/token2022.rs @@ -1,4 +1,4 @@ -// file: kb-lib/src/decoder/spl/token_2022.rs +// file: kb-lib/src/decoder/spl/token2022.rs // version: 2 //! Exact Token-2022 instruction and state decoder component. @@ -9,37 +9,37 @@ mod state; mod wire; /// Maximum prefix retained in bounded Token-2022 diagnostics. -pub(crate) use self::constants::SPL_TOKEN_2022_DIAGNOSTIC_PREFIX_BYTES; +pub(crate) use self::constants::DC_SPL_TOKEN2022_DIAGNOSTIC_PREFIX_BYTES; /// Current stable Token-2022 decoded event contract version. -pub(crate) use self::constants::SPL_TOKEN_2022_EVENT_VERSION; +pub(crate) use self::constants::DC_SPL_TOKEN2022_EVENT_VERSION; /// Exact top-level instruction inventory published by the resolved Token-2022 interface. -pub(crate) use self::constants::SPL_TOKEN_2022_INSTRUCTION_ENTRIES; +pub(crate) use self::constants::DC_SPL_TOKEN2022_INSTRUCTION_ENTRIES; /// Maximum total account metas consumed by one Token-2022 batch. -pub(crate) use self::constants::SPL_TOKEN_2022_MAX_BATCH_ACCOUNTS; +pub(crate) use self::constants::DC_SPL_TOKEN2022_MAX_BATCH_ACCOUNTS; /// Maximum decoded sub-instructions in one Token-2022 batch. -pub(crate) use self::constants::SPL_TOKEN_2022_MAX_BATCH_INSTRUCTIONS; +pub(crate) use self::constants::DC_SPL_TOKEN2022_MAX_BATCH_INSTRUCTIONS; /// Maximum retained Token-2022 instruction payload size. -pub(crate) use self::constants::SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES; +pub(crate) use self::constants::DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES; /// Maximum retained UTF-8 string size for embedded Token Metadata instructions. -pub(crate) use self::constants::SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES; +pub(crate) use self::constants::DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES; /// Stable Token-2022 surface code. -pub(crate) use self::constants::SPL_TOKEN_2022_SURFACE_CODE; +pub(crate) use self::constants::DC_SPL_TOKEN2022_SURFACE_CODE; /// Canonical tracing target for the Token-2022 decoder. -pub(crate) use self::constants::SPL_TOKEN_2022_TRACING_TARGET; +pub(crate) use self::constants::DC_SPL_TOKEN2022_TRACING_TARGET; /// Decodes one bounded Token-2022 instruction. -pub(crate) use self::wire::spl_token_2022_decode; +pub(crate) use self::wire::decoder_spl_token2022_decode; /// Returns the exact entry matching one Token-2022 tag. -pub(crate) use self::wire::spl_token_2022_entry_for_tag; +pub(crate) use self::wire::decoder_spl_token2022_entry_for_tag; /// Returns the first byte of one retained Token-2022 payload. -pub(crate) use self::wire::spl_token_2022_payload_tag; +pub(crate) use self::wire::decoder_spl_token2022_payload_tag; /// Exact decoder for the Token-2022 program. -pub use self::decoder::SplToken2022Decoder; +pub use self::decoder::DcSplToken2022Decoder; /// Parsed Token-2022 Mint, Account, or Multisig state. -pub use self::state::Token2022State; +pub use self::state::DcToken2022State; /// Exact Token-2022 base account state kind. -pub use self::state::Token2022StateKind; +pub use self::state::DcToken2022StateKind; /// One exact Token-2022 TLV entry. -pub use self::state::Token2022TlvEntry; +pub use self::state::DcToken2022TlvEntry; /// Parses one Token-2022 Mint, Account, or Multisig state. -pub use self::state::parse_token_2022_state; +pub use self::state::decoder_spl_token2022_parse_token2022_state; diff --git a/kb-lib/src/decoder/spl/token_2022/constants.rs b/kb-lib/src/decoder/spl/token2022/constants.rs similarity index 78% rename from kb-lib/src/decoder/spl/token_2022/constants.rs rename to kb-lib/src/decoder/spl/token2022/constants.rs index 5340103..f464bbb 100644 --- a/kb-lib/src/decoder/spl/token_2022/constants.rs +++ b/kb-lib/src/decoder/spl/token2022/constants.rs @@ -1,24 +1,24 @@ -// file: kb-lib/src/decoder/spl/token_2022/constants.rs +// file: kb-lib/src/decoder/spl/token2022/constants.rs // version: 1 //! Local constants for the exact Token-2022 decoder. Program identifiers live in `kb_program_ids`. /// Stable Token-2022 surface code. -pub(crate) const SPL_TOKEN_2022_SURFACE_CODE: &str = "spl_token_2022"; +pub(crate) const DC_SPL_TOKEN2022_SURFACE_CODE: &str = "spl_token2022"; /// Current decoded event contract version. -pub(crate) const SPL_TOKEN_2022_EVENT_VERSION: u32 = 1; +pub(crate) const DC_SPL_TOKEN2022_EVENT_VERSION: u32 = 1; /// Maximum retained instruction payload size. -pub(crate) const SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES: usize = 16_384; +pub(crate) const DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES: usize = 16_384; /// Maximum retained UTF-8 string size for embedded Token Metadata instructions. -pub(crate) const SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES: usize = 4_096; +pub(crate) const DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES: usize = 4_096; /// Maximum prefix retained in diagnostics. -pub(crate) const SPL_TOKEN_2022_DIAGNOSTIC_PREFIX_BYTES: usize = 32; +pub(crate) const DC_SPL_TOKEN2022_DIAGNOSTIC_PREFIX_BYTES: usize = 32; /// Maximum decoded sub-instructions in one batch. -pub(crate) const SPL_TOKEN_2022_MAX_BATCH_INSTRUCTIONS: usize = 64; +pub(crate) const DC_SPL_TOKEN2022_MAX_BATCH_INSTRUCTIONS: usize = 64; /// Maximum total account metas consumed by one batch. -pub(crate) const SPL_TOKEN_2022_MAX_BATCH_ACCOUNTS: usize = 512; +pub(crate) const DC_SPL_TOKEN2022_MAX_BATCH_ACCOUNTS: usize = 512; /// Exact top-level instruction inventory published by the resolved Token-2022 interface. -pub(crate) const SPL_TOKEN_2022_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ +pub(crate) const DC_SPL_TOKEN2022_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ (0, "initialize_mint", false), (1, "initialize_account", false), (2, "initialize_multisig", false), @@ -69,4 +69,4 @@ pub(crate) const SPL_TOKEN_2022_INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[ (255, "batch", false), ]; /// Canonical tracing target for this crate. -pub(crate) const SPL_TOKEN_2022_TRACING_TARGET: &str = "kb-lib.decoder.spl.token_2022"; +pub(crate) const DC_SPL_TOKEN2022_TRACING_TARGET: &str = "kb-lib.decoder.spl.token2022"; diff --git a/kb-lib/src/decoder/spl/token_2022/decoder.rs b/kb-lib/src/decoder/spl/token2022/decoder.rs similarity index 82% rename from kb-lib/src/decoder/spl/token_2022/decoder.rs rename to kb-lib/src/decoder/spl/token2022/decoder.rs index 482a93d..1ca2859 100644 --- a/kb-lib/src/decoder/spl/token_2022/decoder.rs +++ b/kb-lib/src/decoder/spl/token2022/decoder.rs @@ -1,23 +1,23 @@ -// file: kb-lib/src/decoder/spl/token_2022/decoder.rs +// file: kb-lib/src/decoder/spl/token2022/decoder.rs // version: 1 //! Exact Token-2022 dispatch for the common decode pipeline. -const TOKEN_SURFACES: &[crate::DecoderSurface] = &[crate::DecoderSurface { - program_id: kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, - surface_code: crate::SPL_TOKEN_2022_SURFACE_CODE, +const TOKEN_SURFACES: &[crate::DcApiDecoderSurface] = &[crate::DcApiDecoderSurface { + program_id: kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + surface_code: crate::DC_SPL_TOKEN2022_SURFACE_CODE, priority: 100, }]; -const PROGRAM_IDS: &[&str] = &[kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID]; +const PROGRAM_IDS: &[&str] = &[kb_program_ids::SPL_TOKEN2022_PROGRAM_ID]; /// Exact decoder for the Token-2022 program. #[derive(Clone, Debug, Default)] -pub struct SplToken2022Decoder; +pub struct DcSplToken2022Decoder; -impl crate::ProtocolDecoder for crate::SplToken2022Decoder { +impl crate::DcApiProtocolDecoder for crate::DcSplToken2022Decoder { fn decoder_name(&self) -> &'static str { - return "kb_decoder_spl_token_2022"; + return "kb_decoder_spl_token2022"; } fn decoder_version(&self) -> &'static str { @@ -30,45 +30,45 @@ impl crate::ProtocolDecoder for crate::SplToken2022Decoder { fn supports_observation( &self, - observation: &crate::ProgramObservation, - ) -> crate::DecoderSupport { - return if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) { - crate::DecoderSupport::Yes + observation: &crate::MdProgramObservation, + ) -> crate::DcApiDecoderSupport { + return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { + crate::DcApiDecoderSupport::Yes } else { - crate::DecoderSupport::No + crate::DcApiDecoderSupport::No }; } fn decode_observation( &self, - _observation: &crate::ProgramObservation, - ) -> kb_core::Result> { + _observation: &crate::MdProgramObservation, + ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::InstructionDecoder for crate::SplToken2022Decoder { - fn identity(&self) -> crate::DecoderIdentity { - return crate::DecoderIdentity { - name: "spl_token_2022".to_string(), +impl crate::DcApiInstructionDecoder for crate::DcSplToken2022Decoder { + fn identity(&self) -> crate::DcApiDecoderIdentity { + return crate::DcApiDecoderIdentity { + name: "spl_token2022".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn surfaces(&self) -> &'static [crate::DecoderSurface] { + fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] { return TOKEN_SURFACES; } - fn coverage(&self) -> std::vec::Vec { - return crate::SPL_TOKEN_2022_INSTRUCTION_ENTRIES + fn coverage(&self) -> std::vec::Vec { + return crate::DC_SPL_TOKEN2022_INSTRUCTION_ENTRIES .iter() .map(|(tag, code, historical)| { - return crate::DecoderCoverageDeclaration { - program_id: kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.to_string(), + return crate::DcApiDecoderCoverageDeclaration { + program_id: kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.to_string(), surface_code: std::option::Option::Some( - crate::SPL_TOKEN_2022_SURFACE_CODE.to_string(), + crate::DC_SPL_TOKEN2022_SURFACE_CODE.to_string(), ), - entry_kind: crate::DecoderCoverageEntryKind::Instruction, + entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction, entry_code: (*code).to_string(), discriminator_hex: std::option::Option::Some(format!("{tag:02x}")), historical: *historical, @@ -77,38 +77,45 @@ impl crate::InstructionDecoder for crate::SplToken2022Decoder { .collect(); } - fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition { - if input.program_id != kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID { - return crate::DecoderRecognition::incompatible(); + fn recognize( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderRecognition { + if input.program_id != kb_program_ids::SPL_TOKEN2022_PROGRAM_ID { + return crate::DcApiDecoderRecognition::incompatible(); } - let tag = crate::spl_token_2022_payload_tag(input); - let entry = tag.and_then(crate::spl_token_2022_entry_for_tag); - return crate::DecoderRecognition::compatible( + let tag = crate::decoder_spl_token2022_payload_tag(input); + let entry = tag.and_then(crate::decoder_spl_token2022_entry_for_tag); + return crate::DcApiDecoderRecognition::compatible( entry.is_some(), 100, - std::option::Option::Some(crate::SPL_TOKEN_2022_SURFACE_CODE.to_string()), + std::option::Option::Some(crate::DC_SPL_TOKEN2022_SURFACE_CODE.to_string()), entry.map(|(_, code, _)| return code.to_string()), tag.map(|value| return format!("{value:02x}")), ); } - fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult { - if input.program_id != kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID { - return crate::DecoderExecutionResult::unsupported(std::option::Option::None); + fn decode( + &self, + input: &crate::MdCoreInstructionReplayInput, + ) -> crate::DcApiDecoderExecutionResult { + if input.program_id != kb_program_ids::SPL_TOKEN2022_PROGRAM_ID { + return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None); } - let result = crate::spl_token_2022_decode(input); + let result = crate::decoder_spl_token2022_decode(input); if matches!( result.status, - crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported + crate::DcApiDecoderOutcomeStatus::Failed + | crate::DcApiDecoderOutcomeStatus::Unsupported ) { tracing::error!( - target: crate::SPL_TOKEN_2022_TRACING_TARGET, + target: crate::DC_SPL_TOKEN2022_TRACING_TARGET, action = "decode_failure", signature = %input.signature, slot = input.slot, instruction_path = %input.instruction_path, program_id = %input.program_id, - processor_name = "spl_token_2022", + processor_name = "spl_token2022", processor_version = env!("CARGO_PKG_VERSION"), input_key = %input.replay_input_key, payload_hash = ?input.instruction_payload_hash, @@ -118,7 +125,7 @@ impl crate::InstructionDecoder for crate::SplToken2022Decoder { ); } tracing::debug!( - target: crate::SPL_TOKEN_2022_TRACING_TARGET, + target: crate::DC_SPL_TOKEN2022_TRACING_TARGET, action = "decode", signature = %input.signature, instruction_path = %input.instruction_path, @@ -142,8 +149,8 @@ mod tests { keys: serde_json::Value, failed: bool, path: &str, - ) -> crate::CoreInstructionReplayInput { - let result = crate::CoreInstructionReplayInput::new( + ) -> crate::MdCoreInstructionReplayInput { + let result = crate::MdCoreInstructionReplayInput::new( format!("signature:{path}"), "signature", 42, @@ -184,12 +191,12 @@ mod tests { } #[test] - fn exact_token_2022_dispatch_decodes_checked_transfer() { + fn exact_token2022_dispatch_decodes_checked_transfer() { let mut wire = std::vec![12]; wire.extend_from_slice(&u64::MAX.to_le_bytes()); wire.push(9); let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([ {"position":0,"accountIndex":0,"accountKey":"account0"}, @@ -206,14 +213,14 @@ mod tests { false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), Some("transfer_checked")); assert_eq!(result.observations.len(), 1); assert!(result.observations[0].observation_committed); assert_eq!( result.observations[0].event.program_id.0, - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID ); assert_eq!( result.observations[0].payload_json["parameters"]["amountRaw"], @@ -223,11 +230,11 @@ mod tests { } #[test] - fn failed_inner_token_2022_instruction_remains_uncommitted() { + fn failed_inner_token2022_instruction_remains_uncommitted() { let mut wire = std::vec![7]; wire.extend_from_slice(&42_u64.to_le_bytes()); let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([ {"position":0,"accountIndex":0,"accountKey":"account0"}, @@ -242,8 +249,8 @@ mod tests { true, "1/0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!(result.recognized_entry_code.as_deref(), Some("mint_to")); assert_eq!(result.observations.len(), 1); assert!(!result.observations[0].observation_committed); @@ -273,15 +280,16 @@ mod tests { ]; for (wire, expected, expected_rate) in cases { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([{"position":0,"accountIndex":0,"accountKey":"account0"}]), serde_json::json!([account(0, true, true)]), false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!(result.recognized_entry_code.as_deref(), Some(expected)); assert_eq!(result.observations[0].event.event_name.0, expected); if !expected_rate.is_null() { @@ -297,20 +305,21 @@ mod tests { fn interest_bearing_wire_rejects_unknown_truncated_and_suffixed_forms() { for wire in [vec![33], vec![33, 0], vec![33, 1, 0], vec![33, 1, 0, 0, 0], vec![33, 2]] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } #[test] - fn embedded_metadata_and_group_interfaces_decode_as_token_2022_leaves() { + fn embedded_metadata_and_group_interfaces_decode_as_token2022_leaves() { fn string(value: &str) -> std::vec::Vec { let mut output = std::vec::Vec::new(); output.extend_from_slice(&(value.len() as u32).to_le_bytes()); @@ -342,19 +351,20 @@ mod tests { }) .collect::>(); let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::Value::Array(instruction_accounts), serde_json::Value::Array(resolved_accounts), false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!(result.recognized_entry_code.as_deref(), Some(expected)); assert_eq!( result.observations[0].event.program_id.0, - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID ); } } @@ -367,22 +377,23 @@ mod tests { { let mut value = vec![0xd2, 0xe1, 0x1e, 0xa2, 0x58, 0xb8, 0x4d, 0x8d]; value.extend_from_slice( - &((crate::SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES + 1) as u32).to_le_bytes(), + &((crate::DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES + 1) as u32).to_le_bytes(), ); value }, ]; for wire in malformed { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -416,15 +427,16 @@ mod tests { update.extend_from_slice(&[11_u8; 32]); for (wire, expected) in [(initialize, initialize_code), (update, update_code)] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([{"position":0,"accountIndex":0,"accountKey":"account0"}]), serde_json::json!([account(0, true, true)]), false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!(result.recognized_entry_code.as_deref(), Some(expected)); assert!( result.observations[0].payload_json["parameters"][address_field].is_string() @@ -451,33 +463,35 @@ mod tests { }, ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "0", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } #[test] - fn classic_token_and_unknown_programs_never_emit_token_2022_events() { + fn classic_token_and_unknown_programs_never_emit_token2022_events() { for program_id in [kb_program_ids::SPL_TOKEN_PROGRAM_ID, kb_program_ids::SYSTEM_PROGRAM_ID] { let input = input(program_id, &[17], serde_json::json!([]), serde_json::json!([]), false, "0"); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported); assert!(result.observations.is_empty()); } } fn matrix() -> serde_json::Value { return match serde_json::from_str(include_str!( - "../../../../../docs/SPL_TOKEN_2022_MATRIX.json" + "../../../../../docs/SPL_TOKEN2022_MATRIX.json" )) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("invalid Token-2022 matrix JSON: {error}"), @@ -487,7 +501,7 @@ mod tests { #[test] fn initial_matrix_has_exact_program_boundary_and_candidate_inventory() { let matrix = matrix(); - assert_eq!(matrix["programId"], kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID); + assert_eq!(matrix["programId"], kb_program_ids::SPL_TOKEN2022_PROGRAM_ID); assert_eq!(matrix["surfaceEquality"]["topLevelInstructionCount"], 48); assert_eq!(matrix["surfaceEquality"]["productionExtensionTypeCount"], 29); assert_eq!(matrix["instructions"].as_array().map(std::vec::Vec::len), Some(48)); @@ -540,11 +554,11 @@ mod tests { let matrix = matrix(); assert_eq!( spl_token_2022_interface::ID.to_string(), - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, ); assert_eq!( spl_elgamal_registry_interface::ID.to_string(), - kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, ); assert_eq!(spl_elgamal_registry_interface::REGISTRY_ADDRESS_SEED, b"elgamal-registry",); assert_eq!(matrix["interfaceAudit"]["resolvedVersion"], "3.1.1"); @@ -556,7 +570,7 @@ mod tests { assert_eq!(matrix["elgamalRegistryBoundary"]["resolvedVersion"], "0.2.1"); assert_eq!( matrix["elgamalRegistryBoundary"]["programId"], - kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID + kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID ); assert_eq!(matrix["elgamalRegistryBoundary"]["sharedDecoder"], false); assert_eq!(matrix["elgamalRegistryBoundary"]["sharedExecutor"], false); @@ -808,15 +822,16 @@ mod tests { ]; for (wire, expected) in cases { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, expected, ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -837,15 +852,16 @@ mod tests { ]; for (wire, expected) in cases { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, expected, ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -864,15 +880,16 @@ mod tests { std::vec![34, 2], ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "invalid", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); assert!(result.observations.is_empty()); } } @@ -906,15 +923,16 @@ mod tests { ]; for (wire, expected) in cases { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, expected, ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -944,15 +962,16 @@ mod tests { }, ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "invalid", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -983,15 +1002,16 @@ mod tests { (std::vec![27, 12], "disable_non_confidential_credits"), ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, expected, ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -1019,15 +1039,16 @@ mod tests { std::vec![27, 15], ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "invalid", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -1060,15 +1081,16 @@ mod tests { (std::vec![27, 14], "configure_confidential_transfer_account_with_registry"), ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, expected, ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -1094,15 +1116,16 @@ mod tests { std::vec![27, 14, 0], ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "invalid", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -1124,21 +1147,22 @@ mod tests { (std::vec![37, 5], "disable_confidential_harvest_to_mint"), ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, expected, ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) ); assert_eq!(result.observations.len(), 1); - assert_eq!(result.observations[0].event.event_family, crate::EventFamily::Fee); + assert_eq!(result.observations[0].event.event_family, crate::MdEventFamily::Fee); } } @@ -1153,15 +1177,16 @@ mod tests { std::vec![37, 6], ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "invalid", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } @@ -1195,15 +1220,16 @@ mod tests { (permissioned, "permissioned_confidential_burn"), ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, expected, ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded, "{expected}"); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded, "{expected}"); assert_eq!( result.recognized_entry_code.as_deref(), std::option::Option::Some(expected) @@ -1224,15 +1250,16 @@ mod tests { std::vec![46, 3, 0], ] { let input = input( - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, wire.as_slice(), serde_json::json!([]), serde_json::json!([]), false, "invalid", ); - let result = crate::InstructionDecoder::decode(&crate::SplToken2022Decoder, &input); - assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed); + let result = + crate::DcApiInstructionDecoder::decode(&crate::DcSplToken2022Decoder, &input); + assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed); } } } diff --git a/kb-lib/src/decoder/spl/token_2022/state.rs b/kb-lib/src/decoder/spl/token2022/state.rs similarity index 86% rename from kb-lib/src/decoder/spl/token_2022/state.rs rename to kb-lib/src/decoder/spl/token2022/state.rs index 32ac749..d4f52e7 100644 --- a/kb-lib/src/decoder/spl/token_2022/state.rs +++ b/kb-lib/src/decoder/spl/token2022/state.rs @@ -1,4 +1,4 @@ -// file: kb-lib/src/decoder/spl/token_2022/state.rs +// file: kb-lib/src/decoder/spl/token2022/state.rs // version: 1 //! Strict Token-2022 base-state and TLV parsing. @@ -17,7 +17,7 @@ const MAX_METADATA_PAIRS: usize = 64; /// Token-2022 account state category selected by the caller. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Token2022StateKind { +pub enum DcToken2022StateKind { /// Mint base state, optionally followed by Token-2022 TLV extensions. Mint, /// Token account base state, optionally followed by Token-2022 TLV extensions. @@ -28,7 +28,7 @@ pub enum Token2022StateKind { /// One bounded Token-2022 TLV extension entry. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Token2022TlvEntry { +pub struct DcToken2022TlvEntry { /// Numeric `ExtensionType` discriminant retained exactly from the wire. pub extension_type: u16, /// Stable name for published types, or `unknown` for a future type. @@ -41,9 +41,9 @@ pub struct Token2022TlvEntry { /// Strictly parsed Token-2022 account state. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Token2022State { +pub struct DcToken2022State { /// Caller-selected base state category. - pub kind: Token2022StateKind, + pub kind: DcToken2022StateKind, /// Structured fields decoded from the exact base layout. pub base_fields: serde_json::Value, /// Base layout bytes encoded as lowercase hexadecimal. @@ -51,14 +51,14 @@ pub struct Token2022State { /// Account-type discriminator for extended Mint or Account states. pub account_type: Option, /// Ordered TLV entries. - pub extensions: Vec, + pub extensions: Vec, } /// Parse one Token-2022 Mint, Account, or Multisig state without interpreting extension payloads. -pub fn parse_token_2022_state( - kind: Token2022StateKind, +pub fn decoder_spl_token2022_parse_token2022_state( + kind: DcToken2022StateKind, data: &[u8], -) -> Result { +) -> Result { if data.len() > MAX_ACCOUNT_DATA_LEN { return Err(format!( "Token-2022 account data length {} exceeds bound {}", @@ -67,16 +67,16 @@ pub fn parse_token_2022_state( )); } return match kind { - Token2022StateKind::Mint => parse_mint(data), - Token2022StateKind::Account => parse_account(data), - Token2022StateKind::Multisig => parse_multisig(data), + DcToken2022StateKind::Mint => parse_mint(data), + DcToken2022StateKind::Account => parse_account(data), + DcToken2022StateKind::Multisig => parse_multisig(data), }; } -fn parse_mint(data: &[u8]) -> Result { +fn parse_mint(data: &[u8]) -> Result { if data.len() == MINT_BASE_LEN { - return Ok(Token2022State { - kind: Token2022StateKind::Mint, + return Ok(DcToken2022State { + kind: DcToken2022StateKind::Mint, base_fields: match parse_mint_base(data) { Ok(value) => value, Err(error) => return Err(error), @@ -105,8 +105,8 @@ fn parse_mint(data: &[u8]) -> Result { Ok(extensions) => extensions, Err(error) => return Err(error), }; - return Ok(Token2022State { - kind: Token2022StateKind::Mint, + return Ok(DcToken2022State { + kind: DcToken2022StateKind::Mint, base_fields: match parse_mint_base(&data[..MINT_BASE_LEN]) { Ok(value) => value, Err(error) => return Err(error), @@ -117,10 +117,10 @@ fn parse_mint(data: &[u8]) -> Result { }); } -fn parse_account(data: &[u8]) -> Result { +fn parse_account(data: &[u8]) -> Result { if data.len() == ACCOUNT_BASE_LEN { - return Ok(Token2022State { - kind: Token2022StateKind::Account, + return Ok(DcToken2022State { + kind: DcToken2022StateKind::Account, base_fields: match parse_account_base(data) { Ok(value) => value, Err(error) => return Err(error), @@ -146,8 +146,8 @@ fn parse_account(data: &[u8]) -> Result { Ok(extensions) => extensions, Err(error) => return Err(error), }; - return Ok(Token2022State { - kind: Token2022StateKind::Account, + return Ok(DcToken2022State { + kind: DcToken2022StateKind::Account, base_fields: match parse_account_base(&data[..ACCOUNT_BASE_LEN]) { Ok(value) => value, Err(error) => return Err(error), @@ -158,15 +158,15 @@ fn parse_account(data: &[u8]) -> Result { }); } -fn parse_multisig(data: &[u8]) -> Result { +fn parse_multisig(data: &[u8]) -> Result { if data.len() != MULTISIG_BASE_LEN { return Err(format!( "Token-2022 multisig requires exactly {MULTISIG_BASE_LEN} bytes, got {}", data.len() )); } - return Ok(Token2022State { - kind: Token2022StateKind::Multisig, + return Ok(DcToken2022State { + kind: DcToken2022StateKind::Multisig, base_fields: match parse_multisig_base(data) { Ok(value) => value, Err(error) => return Err(error), @@ -300,7 +300,7 @@ fn read_i64(data: &[u8]) -> i64 { ]); } -fn parse_tlv(data: &[u8], kind_from_account_type: u8) -> Result, String> { +fn parse_tlv(data: &[u8], kind_from_account_type: u8) -> Result, String> { let mut entries = Vec::new(); let mut offset = 0usize; let mut seen = std::collections::BTreeSet::new(); @@ -340,7 +340,7 @@ fn parse_tlv(data: &[u8], kind_from_account_type: u8) -> Result value_fields, Err(error) => return Err(error), }; - entries.push(Token2022TlvEntry { + entries.push(DcToken2022TlvEntry { extension_type, extension_name: extension_name(extension_type), value_hex: lower_hex(value), @@ -916,10 +916,18 @@ mod tests { #[test] fn exact_base_mint_account_and_multisig_layouts_are_preserved() { - let mint = super::parse_token_2022_state(super::Token2022StateKind::Mint, &[0; 82]); - let account = super::parse_token_2022_state(super::Token2022StateKind::Account, &[0; 165]); - let multisig = - super::parse_token_2022_state(super::Token2022StateKind::Multisig, &[0; 355]); + let mint = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &[0; 82], + ); + let account = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &[0; 165], + ); + let multisig = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Multisig, + &[0; 355], + ); assert_eq!(mint.as_ref().map(|state| return state.base_hex.len()), Ok(164)); assert_eq!(account.as_ref().map(|state| return state.base_hex.len()), Ok(330)); assert_eq!(multisig.as_ref().map(|state| return state.base_hex.len()), Ok(710)); @@ -947,7 +955,10 @@ mod tests { mint.extend_from_slice(&1u16.to_le_bytes()); mint.push(0xcc); mint.extend_from_slice(&[0; 8]); - let parsed_mint = super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + let parsed_mint = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); assert_eq!(parsed_mint.as_ref().map(|state| return state.extensions.len()), Ok(2)); assert_eq!( parsed_mint.as_ref().map(|state| return state.extensions[0].extension_name), @@ -962,8 +973,10 @@ mod tests { account.extend_from_slice(&8u16.to_le_bytes()); account.extend_from_slice(&1u16.to_le_bytes()); account.push(1); - let parsed_account = - super::parse_token_2022_state(super::Token2022StateKind::Account, &account); + let parsed_account = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &account, + ); assert_eq!( parsed_account.as_ref().map(|state| return state.extensions[0].extension_name), Ok("memo_transfer") @@ -982,12 +995,20 @@ mod tests { mint_padding[82] = 1; mint_padding[165] = 1; assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint_padding).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint_padding + ) + .is_err() ); let mut wrong_type = vec![0; 166]; wrong_type[165] = 2; assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &wrong_type).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &wrong_type + ) + .is_err() ); let mut truncated = vec![0; 166]; truncated[165] = 2; @@ -995,7 +1016,11 @@ mod tests { truncated.extend_from_slice(&3u16.to_le_bytes()); truncated.push(9); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &truncated).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &truncated + ) + .is_err() ); let mut duplicate = vec![0; 166]; duplicate[165] = 2; @@ -1005,18 +1030,30 @@ mod tests { duplicate.push(1); } assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &duplicate).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &duplicate + ) + .is_err() ); } #[test] fn state_lengths_and_tlv_count_are_bounded() { assert!( - super::parse_token_2022_state(super::Token2022StateKind::Multisig, &[0; 354]).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Multisig, + &[0; 354] + ) + .is_err() ); let oversized = vec![0; 1_048_577]; assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &oversized).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &oversized + ) + .is_err() ); let mut account = vec![0; 166]; account[165] = 2; @@ -1025,7 +1062,11 @@ mod tests { account.extend_from_slice(&0u16.to_le_bytes()); } assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &account).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &account + ) + .is_err() ); } #[test] @@ -1038,7 +1079,10 @@ mod tests { mint.extend_from_slice(&18u16.to_le_bytes()); mint.extend_from_slice(&64u16.to_le_bytes()); mint.extend_from_slice(&[0; 64]); - let parsed = super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + let parsed = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); assert_eq!( parsed .as_ref() @@ -1057,8 +1101,11 @@ mod tests { incompatible.extend_from_slice(&1u16.to_le_bytes()); incompatible.push(1); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &incompatible) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &incompatible + ) + .is_err() ); } @@ -1070,8 +1117,11 @@ mod tests { invalid_bool.extend_from_slice(&1u16.to_le_bytes()); invalid_bool.push(2); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &invalid_bool) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &invalid_bool + ) + .is_err() ); let mut invalid_pointer = vec![0; 166]; invalid_pointer[165] = 1; @@ -1079,8 +1129,11 @@ mod tests { invalid_pointer.extend_from_slice(&63u16.to_le_bytes()); invalid_pointer.extend_from_slice(&[0; 63]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &invalid_pointer) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &invalid_pointer + ) + .is_err() ); } @@ -1101,7 +1154,10 @@ mod tests { mint.extend_from_slice(&1u16.to_le_bytes()); mint.extend_from_slice(&108u16.to_le_bytes()); mint.extend_from_slice(&config); - let parsed_mint = super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + let parsed_mint = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); assert_eq!( parsed_mint .as_ref() @@ -1117,8 +1173,10 @@ mod tests { account.extend_from_slice(&2u16.to_le_bytes()); account.extend_from_slice(&8u16.to_le_bytes()); account.extend_from_slice(&19u64.to_le_bytes()); - let parsed_account = - super::parse_token_2022_state(super::Token2022StateKind::Account, &account); + let parsed_account = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &account, + ); assert_eq!( parsed_account .as_ref() @@ -1135,7 +1193,11 @@ mod tests { short_config.extend_from_slice(&107u16.to_le_bytes()); short_config.extend_from_slice(&[0; 107]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &short_config).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &short_config + ) + .is_err() ); let mut invalid_basis_points = vec![0; 166]; invalid_basis_points[165] = 1; @@ -1145,8 +1207,11 @@ mod tests { invalid_basis_points.extend_from_slice(&108u16.to_le_bytes()); invalid_basis_points.extend_from_slice(&config); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &invalid_basis_points) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &invalid_basis_points + ) + .is_err() ); let mut short_amount = vec![0; 166]; short_amount[165] = 2; @@ -1154,8 +1219,11 @@ mod tests { short_amount.extend_from_slice(&7u16.to_le_bytes()); short_amount.extend_from_slice(&[0; 7]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &short_amount) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &short_amount + ) + .is_err() ); } @@ -1170,7 +1238,10 @@ mod tests { mint.extend_from_slice(&4u16.to_le_bytes()); mint.extend_from_slice(&65u16.to_le_bytes()); mint.extend_from_slice(&mint_extension); - let parsed_mint = super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + let parsed_mint = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); assert_eq!( parsed_mint .as_ref() @@ -1203,8 +1274,10 @@ mod tests { account.extend_from_slice(&5u16.to_le_bytes()); account.extend_from_slice(&295u16.to_le_bytes()); account.extend_from_slice(&account_extension); - let parsed_account = - super::parse_token_2022_state(super::Token2022StateKind::Account, &account); + let parsed_account = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &account, + ); assert_eq!( parsed_account .as_ref() @@ -1234,7 +1307,11 @@ mod tests { short_mint.extend_from_slice(&64u16.to_le_bytes()); short_mint.extend_from_slice(&[0; 64]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &short_mint).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &short_mint + ) + .is_err() ); let mut invalid_mint_flag = vec![0; 166]; invalid_mint_flag[165] = 1; @@ -1244,8 +1321,11 @@ mod tests { invalid_mint_flag.extend_from_slice(&65u16.to_le_bytes()); invalid_mint_flag.extend_from_slice(&mint_extension); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &invalid_mint_flag) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &invalid_mint_flag + ) + .is_err() ); let mut invalid_account_flag = vec![0; 166]; invalid_account_flag[165] = 2; @@ -1255,8 +1335,8 @@ mod tests { invalid_account_flag.extend_from_slice(&295u16.to_le_bytes()); invalid_account_flag.extend_from_slice(&account_extension); assert!( - super::parse_token_2022_state( - super::Token2022StateKind::Account, + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, &invalid_account_flag ) .is_err() @@ -1276,7 +1356,10 @@ mod tests { mint.extend_from_slice(&10u16.to_le_bytes()); mint.extend_from_slice(&(interest.len() as u16).to_le_bytes()); mint.extend_from_slice(&interest); - let parsed = super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + let parsed = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); assert_eq!( parsed .as_ref() @@ -1295,8 +1378,10 @@ mod tests { scaled_mint.extend_from_slice(&25u16.to_le_bytes()); scaled_mint.extend_from_slice(&(scaled.len() as u16).to_le_bytes()); scaled_mint.extend_from_slice(&scaled); - let parsed_scaled = - super::parse_token_2022_state(super::Token2022StateKind::Mint, &scaled_mint); + let parsed_scaled = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &scaled_mint, + ); assert_eq!( parsed_scaled .as_ref() @@ -1310,8 +1395,10 @@ mod tests { pausable_mint.extend_from_slice(&33u16.to_le_bytes()); pausable_mint.extend_from_slice(&[0; 32]); pausable_mint.push(1); - let parsed_pausable = - super::parse_token_2022_state(super::Token2022StateKind::Mint, &pausable_mint); + let parsed_pausable = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &pausable_mint, + ); assert_eq!( parsed_pausable .as_ref() @@ -1328,8 +1415,11 @@ mod tests { short_interest.extend_from_slice(&51u16.to_le_bytes()); short_interest.extend_from_slice(&[0; 51]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &short_interest) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &short_interest + ) + .is_err() ); let mut invalid_scaled = vec![0; 166]; @@ -1341,8 +1431,11 @@ mod tests { invalid_scaled.extend_from_slice(&0i64.to_le_bytes()); invalid_scaled.extend_from_slice(&1.0f64.to_le_bytes()); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &invalid_scaled) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &invalid_scaled + ) + .is_err() ); let mut invalid_pausable = vec![0; 166]; @@ -1352,8 +1445,11 @@ mod tests { invalid_pausable.extend_from_slice(&[0; 32]); invalid_pausable.push(2); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &invalid_pausable) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &invalid_pausable + ) + .is_err() ); let mut account_marker = vec![0; 166]; @@ -1361,8 +1457,11 @@ mod tests { account_marker.extend_from_slice(&27u16.to_le_bytes()); account_marker.extend_from_slice(&0u16.to_le_bytes()); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &account_marker) - .is_ok() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &account_marker + ) + .is_ok() ); } @@ -1378,8 +1477,10 @@ mod tests { fee_mint.extend_from_slice(&16u16.to_le_bytes()); fee_mint.extend_from_slice(&129u16.to_le_bytes()); fee_mint.extend_from_slice(&fee_config); - let parsed_fee_mint = - super::parse_token_2022_state(super::Token2022StateKind::Mint, &fee_mint); + let parsed_fee_mint = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &fee_mint, + ); assert_eq!( parsed_fee_mint .as_ref() @@ -1399,8 +1500,10 @@ mod tests { fee_account.extend_from_slice(&17u16.to_le_bytes()); fee_account.extend_from_slice(&64u16.to_le_bytes()); fee_account.extend_from_slice(&[4; 64]); - let parsed_fee_account = - super::parse_token_2022_state(super::Token2022StateKind::Account, &fee_account); + let parsed_fee_account = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &fee_account, + ); assert_eq!( parsed_fee_account .as_ref() @@ -1418,8 +1521,10 @@ mod tests { mint_burn.extend_from_slice(&24u16.to_le_bytes()); mint_burn.extend_from_slice(&196u16.to_le_bytes()); mint_burn.extend_from_slice(&mint_burn_extension); - let parsed_mint_burn = - super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint_burn); + let parsed_mint_burn = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint_burn, + ); assert_eq!( parsed_mint_burn .as_ref() @@ -1445,8 +1550,11 @@ mod tests { invalid_fee_flag.extend_from_slice(&129u16.to_le_bytes()); invalid_fee_flag.extend_from_slice(&fee_config); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &invalid_fee_flag) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &invalid_fee_flag + ) + .is_err() ); let mut short_fee_amount = vec![0; 166]; @@ -1455,8 +1563,11 @@ mod tests { short_fee_amount.extend_from_slice(&63u16.to_le_bytes()); short_fee_amount.extend_from_slice(&[0; 63]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Account, &short_fee_amount) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Account, + &short_fee_amount + ) + .is_err() ); let mut short_mint_burn = vec![0; 166]; @@ -1465,8 +1576,11 @@ mod tests { short_mint_burn.extend_from_slice(&195u16.to_le_bytes()); short_mint_burn.extend_from_slice(&[0; 195]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &short_mint_burn) - .is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &short_mint_burn + ) + .is_err() ); } @@ -1482,7 +1596,10 @@ mod tests { mint.extend_from_slice(&21u16.to_le_bytes()); mint.extend_from_slice(&80u16.to_le_bytes()); mint.extend_from_slice(&group); - let parsed_group = super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + let parsed_group = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); assert_eq!( parsed_group .as_ref() @@ -1504,8 +1621,10 @@ mod tests { member_mint.extend_from_slice(&23u16.to_le_bytes()); member_mint.extend_from_slice(&72u16.to_le_bytes()); member_mint.extend_from_slice(&member); - let parsed_member = - super::parse_token_2022_state(super::Token2022StateKind::Mint, &member_mint); + let parsed_member = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &member_mint, + ); assert_eq!( parsed_member .as_ref() @@ -1528,7 +1647,11 @@ mod tests { short_group.extend_from_slice(&79u16.to_le_bytes()); short_group.extend_from_slice(&[0; 79]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &short_group).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &short_group + ) + .is_err() ); let mut invalid_size = vec![0; 166]; invalid_size[165] = 1; @@ -1539,7 +1662,11 @@ mod tests { invalid_size.extend_from_slice(&80u16.to_le_bytes()); invalid_size.extend_from_slice(&group); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &invalid_size).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &invalid_size + ) + .is_err() ); let mut short_member = vec![0; 166]; short_member[165] = 1; @@ -1547,7 +1674,11 @@ mod tests { short_member.extend_from_slice(&71u16.to_le_bytes()); short_member.extend_from_slice(&[0; 71]); assert!( - super::parse_token_2022_state(super::Token2022StateKind::Mint, &short_member).is_err() + super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &short_member + ) + .is_err() ); } @@ -1569,7 +1700,10 @@ mod tests { mint.extend_from_slice(&19u16.to_le_bytes()); mint.extend_from_slice(&(metadata.len() as u16).to_le_bytes()); mint.extend_from_slice(&metadata); - let parsed = super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + let parsed = super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); assert_eq!( parsed .as_ref() @@ -1611,13 +1745,16 @@ mod tests { assert!(parse_metadata_extension(&oversized_value).is_err()); } - fn parse_metadata_extension(value: &[u8]) -> Result { + fn parse_metadata_extension(value: &[u8]) -> Result { let mut mint = vec![0; 166]; mint[165] = 1; mint.extend_from_slice(&19u16.to_le_bytes()); mint.extend_from_slice(&(value.len() as u16).to_le_bytes()); mint.extend_from_slice(value); - return super::parse_token_2022_state(super::Token2022StateKind::Mint, &mint); + return super::decoder_spl_token2022_parse_token2022_state( + super::DcToken2022StateKind::Mint, + &mint, + ); } fn token_metadata_fixture( diff --git a/kb-lib/src/decoder/spl/token_2022/wire.rs b/kb-lib/src/decoder/spl/token2022/wire.rs similarity index 96% rename from kb-lib/src/decoder/spl/token_2022/wire.rs rename to kb-lib/src/decoder/spl/token2022/wire.rs index 2261261..e34b199 100644 --- a/kb-lib/src/decoder/spl/token_2022/wire.rs +++ b/kb-lib/src/decoder/spl/token2022/wire.rs @@ -1,4 +1,4 @@ -// file: kb-lib/src/decoder/spl/token_2022/wire.rs +// file: kb-lib/src/decoder/spl/token2022/wire.rs // version: 1 //! Bounded Token-2022 wire, account and authority decoding. @@ -24,25 +24,25 @@ struct ResolvedAccount { source: serde_json::Value, } -pub(crate) fn spl_token_2022_entry_for_tag( +pub(crate) fn decoder_spl_token2022_entry_for_tag( tag: u8, ) -> std::option::Option<(u8, &'static str, bool)> { - return crate::SPL_TOKEN_2022_INSTRUCTION_ENTRIES + return crate::DC_SPL_TOKEN2022_INSTRUCTION_ENTRIES .iter() .copied() .find(|(candidate, _, _)| return *candidate == tag); } -pub(crate) fn spl_token_2022_payload_tag( - input: &crate::CoreInstructionReplayInput, +pub(crate) fn decoder_spl_token2022_payload_tag( + input: &crate::MdCoreInstructionReplayInput, ) -> std::option::Option { let bytes = decode_payload(input).ok(); return bytes.and_then(|value| return value.first().copied()); } -pub(crate) fn spl_token_2022_decode( - input: &crate::CoreInstructionReplayInput, -) -> crate::DecoderExecutionResult { +pub(crate) fn decoder_spl_token2022_decode( + input: &crate::MdCoreInstructionReplayInput, +) -> crate::DcApiDecoderExecutionResult { let bytes = match decode_payload(input) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { @@ -63,15 +63,15 @@ pub(crate) fn spl_token_2022_decode( ); }, }; - let recognized_code = crate::spl_token_2022_entry_for_tag(tag) + let recognized_code = crate::decoder_spl_token2022_entry_for_tag(tag) .map(|(_, code, _)| return code) .or_else(|| return embedded_interface_code(bytes.as_slice())); if recognized_code.is_none() { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Unsupported, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Unsupported, recognized_entry_code: std::option::Option::None, observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: "unknown_token_instruction_tag_or_interface_discriminator".to_string(), message: format!( "unknown Token-2022 tag or embedded interface discriminator; payloadPrefixHex={}", @@ -132,21 +132,23 @@ pub(crate) fn spl_token_2022_decode( bytes.as_slice(), suffix_length, committed, - format!("token_2022:{}:0", parsed.code), + format!("token2022:{}:0", parsed.code), input.instruction_path.clone(), event_family(parsed.code), ); let mut observations = std::vec![parent]; observations.extend(batch_children); - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Decoded, + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Decoded, recognized_entry_code: std::option::Option::Some(parsed.code.to_string()), observations, diagnostics: std::vec::Vec::new(), }; } -fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result> { +fn decode_payload( + input: &crate::MdCoreInstructionReplayInput, +) -> kb_core::Result> { let payload = match input.instruction_payload_json.as_ref() { std::option::Option::Some(value) => value, std::option::Option::None => { @@ -163,7 +165,7 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< )); }, }; - let maximum_encoded = crate::SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES + let maximum_encoded = crate::DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES .saturating_mul(4) .saturating_div(3) .saturating_add(4); @@ -180,10 +182,10 @@ fn decode_payload(input: &crate::CoreInstructionReplayInput) -> kb_core::Result< ))); }, }; - if decoded.len() > crate::SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES { + if decoded.len() > crate::DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES { return std::result::Result::Err(kb_core::Error::invalid_state(format!( "Token-2022 payload exceeds {} decoded bytes", - crate::SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES + crate::DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES ))); } return std::result::Result::Ok(decoded); @@ -202,7 +204,7 @@ fn parse_instruction( return std::result::Result::Err("empty instruction".to_string()); }, }; - let code = match crate::spl_token_2022_entry_for_tag(tag) { + let code = match crate::decoder_spl_token2022_entry_for_tag(tag) { std::option::Option::Some((_, value, _)) => value, std::option::Option::None => { return std::result::Result::Err(format!("unknown instruction tag {tag}")); @@ -452,10 +454,10 @@ fn read_borsh_string( let length = u32::from_le_bytes([length_bytes[0], length_bytes[1], length_bytes[2], length_bytes[3]]) as usize; - if length > crate::SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES { + if length > crate::DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES { return std::result::Result::Err(format!( "{label} exceeds {} bytes", - crate::SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES + crate::DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES )); } let start = length_end; @@ -1962,7 +1964,7 @@ fn one_parameter(field: &str, value: serde_json::Value) -> serde_json::Value { } fn resolve_accounts( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, ) -> kb_core::Result> { let instruction_accounts = match input.instruction_accounts_json.as_array() { std::option::Option::Some(value) => value, @@ -2328,7 +2330,7 @@ fn valid_account_count(code: &str, count: usize) -> bool { #[allow(clippy::too_many_arguments)] fn observation( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, code: &str, tag: u8, parameters: serde_json::Value, @@ -2340,31 +2342,35 @@ fn observation( committed: bool, event_key: std::string::String, instruction_path: std::string::String, - family: crate::EventFamily, -) -> crate::DecodedObservation { + family: crate::MdEventFamily, +) -> crate::DcApiDecodedObservation { let wire_hash = hash(wire); - let event = crate::DecodedProtocolEvent { - signature: crate::Signature(input.signature.clone()), - slot: crate::Slot(input.slot), - instruction_path: crate::InstructionPath(instruction_path.clone()), - program_id: crate::ProgramId(input.program_id.clone()), - protocol_code: crate::ProtocolCode(crate::SPL_TOKEN_2022_SURFACE_CODE.to_string()), - surface_code: crate::SurfaceCode(crate::SPL_TOKEN_2022_SURFACE_CODE.to_string()), - event_code: crate::EventCode(format!("{}.{}", crate::SPL_TOKEN_2022_SURFACE_CODE, code)), - event_name: crate::EventName(code.to_string()), + let event = crate::MdDecodedProtocolEvent { + signature: crate::MdSignature(input.signature.clone()), + slot: crate::MdSlot(input.slot), + instruction_path: crate::MdInstructionPath(instruction_path.clone()), + program_id: crate::MdProgramId(input.program_id.clone()), + protocol_code: crate::MdProtocolCode(crate::DC_SPL_TOKEN2022_SURFACE_CODE.to_string()), + surface_code: crate::MdSurfaceCode(crate::DC_SPL_TOKEN2022_SURFACE_CODE.to_string()), + event_code: crate::MdEventCode(format!( + "{}.{}", + crate::DC_SPL_TOKEN2022_SURFACE_CODE, + code + )), + event_name: crate::MdEventName(code.to_string()), event_family: family, source_kind: if input.instruction_path.contains('/') { - crate::EventSourceKind::InnerInstruction + crate::MdEventSourceKind::InnerInstruction } else { - crate::EventSourceKind::Instruction + crate::MdEventSourceKind::Instruction }, - confidence: crate::DecoderConfidence::ManualExact, + confidence: crate::MdDecoderConfidence::ManualExact, }; - return crate::DecodedObservation { + return crate::DcApiDecodedObservation { event_key, event, payload_json: serde_json::json!({ - "eventVersion": crate::SPL_TOKEN_2022_EVENT_VERSION, + "eventVersion": crate::DC_SPL_TOKEN2022_EVENT_VERSION, "programId": input.program_id, "instruction": code, "wireTag": tag, @@ -2397,9 +2403,9 @@ fn observation( transaction_failed: input.transaction_failed, transaction_error: input.transaction_err_json.clone(), observation_committed: committed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec![ "spl_token_interface_3_0_0_wire_audit".to_string(), format!("wire_tag:{tag}"), @@ -2410,11 +2416,11 @@ fn observation( } fn batch_observations( - input: &crate::CoreInstructionReplayInput, + input: &crate::MdCoreInstructionReplayInput, bytes: &[u8], accounts: &[ResolvedAccount], ) -> std::result::Result< - (std::vec::Vec, serde_json::Value), + (std::vec::Vec, serde_json::Value), std::string::String, > { if bytes.len() == 1 { @@ -2426,10 +2432,10 @@ fn batch_observations( let mut observations = std::vec::Vec::new(); let mut manifest = std::vec::Vec::new(); while cursor < bytes.len() { - if index >= crate::SPL_TOKEN_2022_MAX_BATCH_INSTRUCTIONS { + if index >= crate::DC_SPL_TOKEN2022_MAX_BATCH_INSTRUCTIONS { return std::result::Result::Err(format!( "Batch exceeds {} sub-instructions", - crate::SPL_TOKEN_2022_MAX_BATCH_INSTRUCTIONS + crate::DC_SPL_TOKEN2022_MAX_BATCH_INSTRUCTIONS )); } let account_count = match bytes.get(cursor).copied() { @@ -2460,7 +2466,8 @@ fn batch_observations( }, }; let account_end = account_cursor.saturating_add(account_count); - if account_end > crate::SPL_TOKEN_2022_MAX_BATCH_ACCOUNTS || account_end > accounts.len() { + if account_end > crate::DC_SPL_TOKEN2022_MAX_BATCH_ACCOUNTS || account_end > accounts.len() + { return std::result::Result::Err(format!( "Batch entry {index} account slice exceeds provided accounts or bound" )); @@ -2484,7 +2491,7 @@ fn batch_observations( child_wire, suffix_length, !input.transaction_failed, - format!("token_2022:batch:{index}"), + format!("token2022:batch:{index}"), format!("{}/batch/{index}", input.instruction_path), event_family(parsed.code), )); @@ -2518,7 +2525,7 @@ fn batch_observations( )); } -fn event_family(code: &str) -> crate::EventFamily { +fn event_family(code: &str) -> crate::MdEventFamily { return match code { "set_authority" | "initialize_multisig" @@ -2528,13 +2535,13 @@ fn event_family(code: &str) -> crate::EventFamily { | "update_interest_bearing_rate" | "update_token_metadata_authority" | "update_token_group_authority" - | "update_token_group_max_size" => crate::EventFamily::Admin, + | "update_token_group_max_size" => crate::MdEventFamily::Admin, "initialize_mint" | "initialize_mint2" | "mint_to" | "mint_to_checked" - | "initialize_non_transferable_mint" => crate::EventFamily::TokenMint, - "burn" | "burn_checked" => crate::EventFamily::TokenBurn, + | "initialize_non_transferable_mint" => crate::MdEventFamily::TokenMint, + "burn" | "burn_checked" => crate::MdEventFamily::TokenBurn, "initialize_transfer_fee_config" | "set_transfer_fee" | "withdraw_withheld_tokens_from_mint" @@ -2547,23 +2554,23 @@ fn event_family(code: &str) -> crate::EventFamily { | "harvest_confidential_withheld_tokens_to_mint" | "enable_confidential_harvest_to_mint" | "disable_confidential_harvest_to_mint" - | "transfer_confidential_tokens_with_fee" => crate::EventFamily::Fee, + | "transfer_confidential_tokens_with_fee" => crate::MdEventFamily::Fee, "initialize_default_account_state" | "update_default_account_state" | "enable_required_transfer_memos" | "disable_required_transfer_memos" | "enable_cpi_guard" - | "disable_cpi_guard" => crate::EventFamily::Audit, + | "disable_cpi_guard" => crate::MdEventFamily::Audit, "initialize_token_metadata" | "update_token_metadata_field" | "remove_token_metadata_key" | "emit_token_metadata" | "initialize_token_group" - | "initialize_token_group_member" => crate::EventFamily::Metadata, + | "initialize_token_group_member" => crate::MdEventFamily::Metadata, "batch" | "get_account_data_size" | "amount_to_ui_amount" | "ui_amount_to_amount" => { - crate::EventFamily::Audit + crate::MdEventFamily::Audit }, - _ => crate::EventFamily::TokenAccount, + _ => crate::MdEventFamily::TokenAccount, }; } @@ -2577,7 +2584,7 @@ fn hash(bytes: &[u8]) -> std::string::String { } fn hex_prefix(bytes: &[u8]) -> std::string::String { - let length = std::cmp::min(bytes.len(), crate::SPL_TOKEN_2022_DIAGNOSTIC_PREFIX_BYTES); + let length = std::cmp::min(bytes.len(), crate::DC_SPL_TOKEN2022_DIAGNOSTIC_PREFIX_BYTES); let mut output = std::string::String::with_capacity(length.saturating_mul(2)); for byte in &bytes[..length] { output.push_str(format!("{byte:02x}").as_str()); @@ -2589,12 +2596,12 @@ fn failed( entry_code: std::option::Option<&str>, code: &str, message: std::string::String, -) -> crate::DecoderExecutionResult { - return crate::DecoderExecutionResult { - status: crate::DecoderOutcomeStatus::Failed, +) -> crate::DcApiDecoderExecutionResult { + return crate::DcApiDecoderExecutionResult { + status: crate::DcApiDecoderOutcomeStatus::Failed, recognized_entry_code: entry_code.map(str::to_string), observations: std::vec::Vec::new(), - diagnostics: std::vec![crate::DecoderDiagnostic { + diagnostics: std::vec![crate::DcApiDecoderDiagnostic { code: code.to_string(), message, retriable: false, diff --git a/kb-lib/src/decoder/stable.rs b/kb-lib/src/decoder/stable.rs index 1faa4ac..ba8e2ea 100644 --- a/kb-lib/src/decoder/stable.rs +++ b/kb-lib/src/decoder/stable.rs @@ -3,7 +3,7 @@ //! `stable` decoder family. -pub mod swap_hylo_exchange; -pub mod swap_jupiter_stable; -pub mod swap_numeraire; -pub mod swap_stabble; +mod swap_hylo_exchange; +mod swap_jupiter_stable; +mod swap_numeraire; +mod swap_stabble; diff --git a/kb-lib/src/decoder/stable/swap_hylo_exchange.rs b/kb-lib/src/decoder/stable/swap_hylo_exchange.rs index 668ecbc..ffeb0b7 100644 --- a/kb-lib/src/decoder/stable/swap_hylo_exchange.rs +++ b/kb-lib/src/decoder/stable/swap_hylo_exchange.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_stable_swap_hylo_exchange`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_stable_swap_hylo_exchange"; +const LEGACY_CRATE: &str = "kb_decoder_stable_swap_hylo_exchange"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/stable/swap_jupiter_stable.rs b/kb-lib/src/decoder/stable/swap_jupiter_stable.rs index e07f3c0..a0f3248 100644 --- a/kb-lib/src/decoder/stable/swap_jupiter_stable.rs +++ b/kb-lib/src/decoder/stable/swap_jupiter_stable.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_stable_swap_jupiter_stable`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_stable_swap_jupiter_stable"; +const LEGACY_CRATE: &str = "kb_decoder_stable_swap_jupiter_stable"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/stable/swap_numeraire.rs b/kb-lib/src/decoder/stable/swap_numeraire.rs index bf10ea5..a460c30 100644 --- a/kb-lib/src/decoder/stable/swap_numeraire.rs +++ b/kb-lib/src/decoder/stable/swap_numeraire.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_stable_swap_numeraire`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_stable_swap_numeraire"; +const LEGACY_CRATE: &str = "kb_decoder_stable_swap_numeraire"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/stable/swap_stabble.rs b/kb-lib/src/decoder/stable/swap_stabble.rs index 3680e6b..30e4be2 100644 --- a/kb-lib/src/decoder/stable/swap_stabble.rs +++ b/kb-lib/src/decoder/stable/swap_stabble.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_stable_swap_stabble`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_stable_swap_stabble"; +const LEGACY_CRATE: &str = "kb_decoder_stable_swap_stabble"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/staking.rs b/kb-lib/src/decoder/staking.rs index e8cec74..2d543f2 100644 --- a/kb-lib/src/decoder/staking.rs +++ b/kb-lib/src/decoder/staking.rs @@ -3,6 +3,6 @@ //! `staking` decoder family. -pub mod kamino_farm; -pub mod marinade_finance; -pub mod solayer; +mod kamino_farm; +mod marinade_finance; +mod solayer; diff --git a/kb-lib/src/decoder/staking/kamino_farm.rs b/kb-lib/src/decoder/staking/kamino_farm.rs index cf3578e..9d5f8af 100644 --- a/kb-lib/src/decoder/staking/kamino_farm.rs +++ b/kb-lib/src/decoder/staking/kamino_farm.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_staking_kamino_farm`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_staking_kamino_farm"; +const LEGACY_CRATE: &str = "kb_decoder_staking_kamino_farm"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/staking/marinade_finance.rs b/kb-lib/src/decoder/staking/marinade_finance.rs index d78e821..6d550bd 100644 --- a/kb-lib/src/decoder/staking/marinade_finance.rs +++ b/kb-lib/src/decoder/staking/marinade_finance.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_staking_marinade_finance`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_staking_marinade_finance"; +const LEGACY_CRATE: &str = "kb_decoder_staking_marinade_finance"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/staking/solayer.rs b/kb-lib/src/decoder/staking/solayer.rs index 24ce55e..e5bd11a 100644 --- a/kb-lib/src/decoder/staking/solayer.rs +++ b/kb-lib/src/decoder/staking/solayer.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_staking_solayer`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_staking_solayer"; +const LEGACY_CRATE: &str = "kb_decoder_staking_solayer"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/treasury.rs b/kb-lib/src/decoder/treasury.rs index df134a1..e346807 100644 --- a/kb-lib/src/decoder/treasury.rs +++ b/kb-lib/src/decoder/treasury.rs @@ -3,4 +3,4 @@ //! `treasury` decoder family. -pub mod helium_treasury_management; +mod helium_treasury_management; diff --git a/kb-lib/src/decoder/treasury/helium_treasury_management.rs b/kb-lib/src/decoder/treasury/helium_treasury_management.rs index 0c7f343..19a8abb 100644 --- a/kb-lib/src/decoder/treasury/helium_treasury_management.rs +++ b/kb-lib/src/decoder/treasury/helium_treasury_management.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_treasury_helium_treasury_management`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_treasury_helium_treasury_management"; +const LEGACY_CRATE: &str = "kb_decoder_treasury_helium_treasury_management"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/vault.rs b/kb-lib/src/decoder/vault.rs index e62911a..a94e727 100644 --- a/kb-lib/src/decoder/vault.rs +++ b/kb-lib/src/decoder/vault.rs @@ -3,9 +3,9 @@ //! `vault` decoder family. -pub mod carrot_defi; -pub mod hylo_stability_pool; -pub mod kamino; -pub mod kamino_v2; -pub mod kamino_yvaults; -pub mod meteora; +mod carrot_defi; +mod hylo_stability_pool; +mod kamino; +mod kamino_v2; +mod kamino_yvaults; +mod meteora; diff --git a/kb-lib/src/decoder/vault/carrot_defi.rs b/kb-lib/src/decoder/vault/carrot_defi.rs index ab3e985..5270f6d 100644 --- a/kb-lib/src/decoder/vault/carrot_defi.rs +++ b/kb-lib/src/decoder/vault/carrot_defi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_vault_carrot_defi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_vault_carrot_defi"; +const LEGACY_CRATE: &str = "kb_decoder_vault_carrot_defi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/vault/hylo_stability_pool.rs b/kb-lib/src/decoder/vault/hylo_stability_pool.rs index 3523575..f7b9ec5 100644 --- a/kb-lib/src/decoder/vault/hylo_stability_pool.rs +++ b/kb-lib/src/decoder/vault/hylo_stability_pool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_vault_hylo_stability_pool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_vault_hylo_stability_pool"; +const LEGACY_CRATE: &str = "kb_decoder_vault_hylo_stability_pool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/vault/kamino.rs b/kb-lib/src/decoder/vault/kamino.rs index ebc03f6..e197850 100644 --- a/kb-lib/src/decoder/vault/kamino.rs +++ b/kb-lib/src/decoder/vault/kamino.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_vault_kamino`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_vault_kamino"; +const LEGACY_CRATE: &str = "kb_decoder_vault_kamino"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/vault/kamino_v2.rs b/kb-lib/src/decoder/vault/kamino_v2.rs index 99bed69..dbdc10b 100644 --- a/kb-lib/src/decoder/vault/kamino_v2.rs +++ b/kb-lib/src/decoder/vault/kamino_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_vault_kamino_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_vault_kamino_v2"; +const LEGACY_CRATE: &str = "kb_decoder_vault_kamino_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/vault/kamino_yvaults.rs b/kb-lib/src/decoder/vault/kamino_yvaults.rs index fce5680..5bfe555 100644 --- a/kb-lib/src/decoder/vault/kamino_yvaults.rs +++ b/kb-lib/src/decoder/vault/kamino_yvaults.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_vault_kamino_yvaults`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_vault_kamino_yvaults"; +const LEGACY_CRATE: &str = "kb_decoder_vault_kamino_yvaults"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/vault/meteora.rs b/kb-lib/src/decoder/vault/meteora.rs index 7c5732f..3ef46b7 100644 --- a/kb-lib/src/decoder/vault/meteora.rs +++ b/kb-lib/src/decoder/vault/meteora.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_vault_meteora`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_vault_meteora"; +const LEGACY_CRATE: &str = "kb_decoder_vault_meteora"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/vesting.rs b/kb-lib/src/decoder/vesting.rs index 5a0aee5..3904370 100644 --- a/kb-lib/src/decoder/vesting.rs +++ b/kb-lib/src/decoder/vesting.rs @@ -3,4 +3,4 @@ //! `vesting` decoder family. -pub mod streamflow; +mod streamflow; diff --git a/kb-lib/src/decoder/vesting/streamflow.rs b/kb-lib/src/decoder/vesting/streamflow.rs index cfacc41..6dba305 100644 --- a/kb-lib/src/decoder/vesting/streamflow.rs +++ b/kb-lib/src/decoder/vesting/streamflow.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_vesting_streamflow`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_vesting_streamflow"; +const LEGACY_CRATE: &str = "kb_decoder_vesting_streamflow"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/wallet.rs b/kb-lib/src/decoder/wallet.rs index f260b88..b311150 100644 --- a/kb-lib/src/decoder/wallet.rs +++ b/kb-lib/src/decoder/wallet.rs @@ -3,4 +3,4 @@ //! `wallet` decoder family. -pub mod jupiter_apepro_smart_wallet; +mod jupiter_apepro_smart_wallet; diff --git a/kb-lib/src/decoder/wallet/jupiter_apepro_smart_wallet.rs b/kb-lib/src/decoder/wallet/jupiter_apepro_smart_wallet.rs index 771454c..07d4892 100644 --- a/kb-lib/src/decoder/wallet/jupiter_apepro_smart_wallet.rs +++ b/kb-lib/src/decoder/wallet/jupiter_apepro_smart_wallet.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_wallet_jupiter_apepro_smart_wallet`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_wallet_jupiter_apepro_smart_wallet"; +const LEGACY_CRATE: &str = "kb_decoder_wallet_jupiter_apepro_smart_wallet"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/decoder/weighted.rs b/kb-lib/src/decoder/weighted.rs index 206c266..0d87088 100644 --- a/kb-lib/src/decoder/weighted.rs +++ b/kb-lib/src/decoder/weighted.rs @@ -3,4 +3,4 @@ //! `weighted` decoder family. -pub mod swap_stabble; +mod swap_stabble; diff --git a/kb-lib/src/decoder/weighted/swap_stabble.rs b/kb-lib/src/decoder/weighted/swap_stabble.rs index 60aed3e..99366aa 100644 --- a/kb-lib/src/decoder/weighted/swap_stabble.rs +++ b/kb-lib/src/decoder/weighted/swap_stabble.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_decoder_weighted_swap_stabble`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_decoder_weighted_swap_stabble"; +const LEGACY_CRATE: &str = "kb_decoder_weighted_swap_stabble"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor.rs b/kb-lib/src/executor.rs index 9e58a78..b3cdff8 100644 --- a/kb-lib/src/executor.rs +++ b/kb-lib/src/executor.rs @@ -3,31 +3,81 @@ //! Consolidated executor modules. -pub mod adapter; -pub mod admin; -pub mod amm; -pub mod api; -pub mod bridge; -pub mod clmm; -pub mod cpmm; -pub mod dlmm; -pub mod fees; -pub mod governance; -pub mod launchpad; -pub mod lending; -pub mod lock; -pub mod metadata; -pub mod nft; -pub mod orderbook; -pub mod perpetuals; -pub mod router; -pub mod rwa; -pub mod solana; -pub mod spl; -pub mod stable; -pub mod staking; -pub mod treasury; -pub mod vault; -pub mod vesting; -pub mod wallet; -pub mod weighted; +mod adapter; +mod admin; +mod amm; +mod api; +mod bridge; +mod clmm; +mod cpmm; +mod dlmm; +mod fees; +mod governance; +mod launchpad; +mod lending; +mod lock; +mod metadata; +mod nft; +mod orderbook; +mod perpetuals; +mod router; +mod rwa; +mod solana; +mod spl; +mod stable; +mod staking; +mod treasury; +mod vault; +mod vesting; +mod wallet; +mod weighted; +/// Exposes the blockhash policy kind. +pub use self::api::ExApiExecutionBlockhashKind; +/// Exposes the blockhash policy. +pub use self::api::ExApiExecutionBlockhashPolicy; +/// Exposes the exact execution capability result. +pub use self::api::ExApiExecutionCapability; +/// Exposes supported Solana clusters. +pub use self::api::ExApiExecutionCluster; +/// Exposes cluster restrictions. +pub use self::api::ExApiExecutionClusterPolicy; +/// Exposes the result of waiting for transaction confirmation. +pub use self::api::ExApiExecutionConfirmationResult; +/// Exposes transaction confirmation states. +pub use self::api::ExApiExecutionConfirmationStatus; +/// Exposes explicit execution cost ceilings. +pub use self::api::ExApiExecutionCostLimit; +/// Exposes the legacy common execution plan type. +pub use self::api::ExApiExecutionPlan; +/// Exposes the complete execution policy. +pub use self::api::ExApiExecutionPolicy; +/// Exposes the legacy common execution request type. +pub use self::api::ExApiExecutionRequest; +/// Exposes the result of a transaction send adapter. +pub use self::api::ExApiExecutionSendResult; +/// Exposes the simulation policy. +pub use self::api::ExApiExecutionSimulationPolicy; +/// Exposes the simulation result contract. +pub use self::api::ExApiExecutionSimulationResult; +/// Exposes the legacy common execution support enum. +pub use self::api::ExApiExecutionSupport; +/// Exposes the legacy common instruction executor trait. +pub use self::api::ExApiInstructionExecutor; +/// Exposes one planned instruction account. +pub use self::api::ExApiPlannedAccount; +/// Exposes one encoded planned instruction. +pub use self::api::ExApiPlannedInstruction; +/// Exposes post-execution replay diagnostics. +pub use self::api::ExApiPostExecutionDiagnostic; +/// Exposes post-execution validation requirements. +pub use self::api::ExApiPostExecutionValidationPolicy; +/// Exposes a typed execution plan. +pub use self::api::ExApiPreparedExecutionPlan; +/// Exposes one required signer. +pub use self::api::ExApiRequiredSigner; +/// Exposes the typed executor contract. +pub use self::api::ExApiTypedInstructionExecutor; +/// Exposes the compact JSON payload serializer. +pub use self::api::executor_api_serialize_payload_json; +/// Exposes the pretty JSON payload serializer. +pub use self::api::executor_api_serialize_payload_json_pretty; diff --git a/kb-lib/src/executor/adapter.rs b/kb-lib/src/executor/adapter.rs index 9b6e95e..e4794e5 100644 --- a/kb-lib/src/executor/adapter.rs +++ b/kb-lib/src/executor/adapter.rs @@ -3,4 +3,4 @@ //! `adapter` executor family. -pub mod saber_decimal_wrapper; +mod saber_decimal_wrapper; diff --git a/kb-lib/src/executor/adapter/saber_decimal_wrapper.rs b/kb-lib/src/executor/adapter/saber_decimal_wrapper.rs index bfa640e..c6e82a8 100644 --- a/kb-lib/src/executor/adapter/saber_decimal_wrapper.rs +++ b/kb-lib/src/executor/adapter/saber_decimal_wrapper.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_adapter_saber_decimal_wrapper`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_adapter_saber_decimal_wrapper"; +const LEGACY_CRATE: &str = "kb_executor_adapter_saber_decimal_wrapper"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/admin.rs b/kb-lib/src/executor/admin.rs index 85aa52c..487fd2a 100644 --- a/kb-lib/src/executor/admin.rs +++ b/kb-lib/src/executor/admin.rs @@ -3,5 +3,5 @@ //! `admin` executor family. -pub mod jupiter_lock; -pub mod pump_fees; +mod jupiter_lock; +mod pump_fees; diff --git a/kb-lib/src/executor/admin/jupiter_lock.rs b/kb-lib/src/executor/admin/jupiter_lock.rs index 9b417e2..77c55a9 100644 --- a/kb-lib/src/executor/admin/jupiter_lock.rs +++ b/kb-lib/src/executor/admin/jupiter_lock.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_admin_jupiter_lock`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_admin_jupiter_lock"; +const LEGACY_CRATE: &str = "kb_executor_admin_jupiter_lock"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/admin/pump_fees.rs b/kb-lib/src/executor/admin/pump_fees.rs index 5fce2fa..8ba9de5 100644 --- a/kb-lib/src/executor/admin/pump_fees.rs +++ b/kb-lib/src/executor/admin/pump_fees.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_admin_pump_fees`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_admin_pump_fees"; +const LEGACY_CRATE: &str = "kb_executor_admin_pump_fees"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm.rs b/kb-lib/src/executor/amm.rs index bb5c941..c87f3e4 100644 --- a/kb-lib/src/executor/amm.rs +++ b/kb-lib/src/executor/amm.rs @@ -3,29 +3,29 @@ //! `amm` executor family. -pub mod aldrin_v1; -pub mod aldrin_v2; -pub mod alphaq; -pub mod believe; -pub mod bonk_swap; -pub mod fluxbeam; -pub mod goon_fi; -pub mod goosefx_gamma; -pub mod goosefx_v2; -pub mod guac_swap; -pub mod lifinity_swap_v2; -pub mod metadao_futarchy_amm; -pub mod metadao_v0_5; -pub mod meteora_damm_v1; -pub mod meteora_damm_v2; -pub mod obric_v2; -pub mod one_dex; -pub mod pump_swap; -pub mod raydium_lp_v4; -pub mod solfi; -pub mod solfi_v2; -pub mod vertigo; -pub mod virtuals; -pub mod woofi; -pub mod zero_fi; -pub mod zora; +mod aldrin_v1; +mod aldrin_v2; +mod alphaq; +mod believe; +mod bonk_swap; +mod fluxbeam; +mod goon_fi; +mod goosefx_gamma; +mod goosefx_v2; +mod guac_swap; +mod lifinity_swap_v2; +mod metadao_futarchy_amm; +mod metadao_v0_5; +mod meteora_damm_v1; +mod meteora_damm_v2; +mod obric_v2; +mod one_dex; +mod pump_swap; +mod raydium_lp_v4; +mod solfi; +mod solfi_v2; +mod vertigo; +mod virtuals; +mod woofi; +mod zero_fi; +mod zora; diff --git a/kb-lib/src/executor/amm/aldrin_v1.rs b/kb-lib/src/executor/amm/aldrin_v1.rs index 48e1c2e..2651535 100644 --- a/kb-lib/src/executor/amm/aldrin_v1.rs +++ b/kb-lib/src/executor/amm/aldrin_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_aldrin_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_aldrin_v1"; +const LEGACY_CRATE: &str = "kb_executor_amm_aldrin_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/aldrin_v2.rs b/kb-lib/src/executor/amm/aldrin_v2.rs index 6688a49..139670b 100644 --- a/kb-lib/src/executor/amm/aldrin_v2.rs +++ b/kb-lib/src/executor/amm/aldrin_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_aldrin_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_aldrin_v2"; +const LEGACY_CRATE: &str = "kb_executor_amm_aldrin_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/alphaq.rs b/kb-lib/src/executor/amm/alphaq.rs index 8aa3790..d97dd38 100644 --- a/kb-lib/src/executor/amm/alphaq.rs +++ b/kb-lib/src/executor/amm/alphaq.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_alphaq`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_alphaq"; +const LEGACY_CRATE: &str = "kb_executor_amm_alphaq"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/believe.rs b/kb-lib/src/executor/amm/believe.rs index 97863ac..4185a63 100644 --- a/kb-lib/src/executor/amm/believe.rs +++ b/kb-lib/src/executor/amm/believe.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_believe`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_believe"; +const LEGACY_CRATE: &str = "kb_executor_amm_believe"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/bonk_swap.rs b/kb-lib/src/executor/amm/bonk_swap.rs index cf8f42d..c522505 100644 --- a/kb-lib/src/executor/amm/bonk_swap.rs +++ b/kb-lib/src/executor/amm/bonk_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_bonk_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_bonk_swap"; +const LEGACY_CRATE: &str = "kb_executor_amm_bonk_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/fluxbeam.rs b/kb-lib/src/executor/amm/fluxbeam.rs index eb41497..e3c5c3f 100644 --- a/kb-lib/src/executor/amm/fluxbeam.rs +++ b/kb-lib/src/executor/amm/fluxbeam.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_fluxbeam`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_fluxbeam"; +const LEGACY_CRATE: &str = "kb_executor_amm_fluxbeam"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/goon_fi.rs b/kb-lib/src/executor/amm/goon_fi.rs index 0ea86c4..ebda121 100644 --- a/kb-lib/src/executor/amm/goon_fi.rs +++ b/kb-lib/src/executor/amm/goon_fi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_goon_fi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_goon_fi"; +const LEGACY_CRATE: &str = "kb_executor_amm_goon_fi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/goosefx_gamma.rs b/kb-lib/src/executor/amm/goosefx_gamma.rs index 7fdd2ac..5da8682 100644 --- a/kb-lib/src/executor/amm/goosefx_gamma.rs +++ b/kb-lib/src/executor/amm/goosefx_gamma.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_goosefx_gamma`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_goosefx_gamma"; +const LEGACY_CRATE: &str = "kb_executor_amm_goosefx_gamma"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/goosefx_v2.rs b/kb-lib/src/executor/amm/goosefx_v2.rs index 769761c..080377f 100644 --- a/kb-lib/src/executor/amm/goosefx_v2.rs +++ b/kb-lib/src/executor/amm/goosefx_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_goosefx_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_goosefx_v2"; +const LEGACY_CRATE: &str = "kb_executor_amm_goosefx_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/guac_swap.rs b/kb-lib/src/executor/amm/guac_swap.rs index 941c19e..2d961ba 100644 --- a/kb-lib/src/executor/amm/guac_swap.rs +++ b/kb-lib/src/executor/amm/guac_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_guac_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_guac_swap"; +const LEGACY_CRATE: &str = "kb_executor_amm_guac_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/lifinity_swap_v2.rs b/kb-lib/src/executor/amm/lifinity_swap_v2.rs index b95aa3b..6bbd483 100644 --- a/kb-lib/src/executor/amm/lifinity_swap_v2.rs +++ b/kb-lib/src/executor/amm/lifinity_swap_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_lifinity_swap_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_lifinity_swap_v2"; +const LEGACY_CRATE: &str = "kb_executor_amm_lifinity_swap_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/metadao_futarchy_amm.rs b/kb-lib/src/executor/amm/metadao_futarchy_amm.rs index 1512038..40b5148 100644 --- a/kb-lib/src/executor/amm/metadao_futarchy_amm.rs +++ b/kb-lib/src/executor/amm/metadao_futarchy_amm.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_metadao_futarchy_amm`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_metadao_futarchy_amm"; +const LEGACY_CRATE: &str = "kb_executor_amm_metadao_futarchy_amm"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/metadao_v0_5.rs b/kb-lib/src/executor/amm/metadao_v0_5.rs index ba3dc52..d1a8ddc 100644 --- a/kb-lib/src/executor/amm/metadao_v0_5.rs +++ b/kb-lib/src/executor/amm/metadao_v0_5.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_metadao_v0_5`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_metadao_v0_5"; +const LEGACY_CRATE: &str = "kb_executor_amm_metadao_v0_5"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/meteora_damm_v1.rs b/kb-lib/src/executor/amm/meteora_damm_v1.rs index 3333ec5..b31f08d 100644 --- a/kb-lib/src/executor/amm/meteora_damm_v1.rs +++ b/kb-lib/src/executor/amm/meteora_damm_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_meteora_damm_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_meteora_damm_v1"; +const LEGACY_CRATE: &str = "kb_executor_amm_meteora_damm_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/meteora_damm_v2.rs b/kb-lib/src/executor/amm/meteora_damm_v2.rs index 9cc61a8..b00faf9 100644 --- a/kb-lib/src/executor/amm/meteora_damm_v2.rs +++ b/kb-lib/src/executor/amm/meteora_damm_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_meteora_damm_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_meteora_damm_v2"; +const LEGACY_CRATE: &str = "kb_executor_amm_meteora_damm_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/obric_v2.rs b/kb-lib/src/executor/amm/obric_v2.rs index 60519ab..752cb9a 100644 --- a/kb-lib/src/executor/amm/obric_v2.rs +++ b/kb-lib/src/executor/amm/obric_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_obric_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_obric_v2"; +const LEGACY_CRATE: &str = "kb_executor_amm_obric_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/one_dex.rs b/kb-lib/src/executor/amm/one_dex.rs index 538b549..0d89e88 100644 --- a/kb-lib/src/executor/amm/one_dex.rs +++ b/kb-lib/src/executor/amm/one_dex.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_one_dex`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_one_dex"; +const LEGACY_CRATE: &str = "kb_executor_amm_one_dex"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/pump_swap.rs b/kb-lib/src/executor/amm/pump_swap.rs index 511e8de..1216c8a 100644 --- a/kb-lib/src/executor/amm/pump_swap.rs +++ b/kb-lib/src/executor/amm/pump_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_pump_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_pump_swap"; +const LEGACY_CRATE: &str = "kb_executor_amm_pump_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/raydium_lp_v4.rs b/kb-lib/src/executor/amm/raydium_lp_v4.rs index 1207165..1f67425 100644 --- a/kb-lib/src/executor/amm/raydium_lp_v4.rs +++ b/kb-lib/src/executor/amm/raydium_lp_v4.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_raydium_lp_v4`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_raydium_lp_v4"; +const LEGACY_CRATE: &str = "kb_executor_amm_raydium_lp_v4"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/solfi.rs b/kb-lib/src/executor/amm/solfi.rs index 8aa1097..79ce671 100644 --- a/kb-lib/src/executor/amm/solfi.rs +++ b/kb-lib/src/executor/amm/solfi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_solfi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_solfi"; +const LEGACY_CRATE: &str = "kb_executor_amm_solfi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/solfi_v2.rs b/kb-lib/src/executor/amm/solfi_v2.rs index 1448257..373d91d 100644 --- a/kb-lib/src/executor/amm/solfi_v2.rs +++ b/kb-lib/src/executor/amm/solfi_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_solfi_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_solfi_v2"; +const LEGACY_CRATE: &str = "kb_executor_amm_solfi_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/vertigo.rs b/kb-lib/src/executor/amm/vertigo.rs index 022a429..b3a1ad7 100644 --- a/kb-lib/src/executor/amm/vertigo.rs +++ b/kb-lib/src/executor/amm/vertigo.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_vertigo`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_vertigo"; +const LEGACY_CRATE: &str = "kb_executor_amm_vertigo"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/virtuals.rs b/kb-lib/src/executor/amm/virtuals.rs index 6b4fdfc..b5586d9 100644 --- a/kb-lib/src/executor/amm/virtuals.rs +++ b/kb-lib/src/executor/amm/virtuals.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_virtuals`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_virtuals"; +const LEGACY_CRATE: &str = "kb_executor_amm_virtuals"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/woofi.rs b/kb-lib/src/executor/amm/woofi.rs index 50fea7d..45b9786 100644 --- a/kb-lib/src/executor/amm/woofi.rs +++ b/kb-lib/src/executor/amm/woofi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_woofi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_woofi"; +const LEGACY_CRATE: &str = "kb_executor_amm_woofi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/zero_fi.rs b/kb-lib/src/executor/amm/zero_fi.rs index 168aaf1..09505d4 100644 --- a/kb-lib/src/executor/amm/zero_fi.rs +++ b/kb-lib/src/executor/amm/zero_fi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_zero_fi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_zero_fi"; +const LEGACY_CRATE: &str = "kb_executor_amm_zero_fi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/amm/zora.rs b/kb-lib/src/executor/amm/zora.rs index b36d341..e49fc62 100644 --- a/kb-lib/src/executor/amm/zora.rs +++ b/kb-lib/src/executor/amm/zora.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_amm_zora`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_amm_zora"; +const LEGACY_CRATE: &str = "kb_executor_amm_zora"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/api.rs b/kb-lib/src/executor/api.rs index c49a959..14f2c38 100644 --- a/kb-lib/src/executor/api.rs +++ b/kb-lib/src/executor/api.rs @@ -3,55 +3,55 @@ //! Executor contracts consolidated from `kb_execution_api`. -pub mod execution; -pub mod executor; +mod execution; +mod executor; /// Exposes the blockhash policy kind. -pub use crate::executor::api::execution::ExecutionBlockhashKind; +pub use self::execution::ExApiExecutionBlockhashKind; /// Exposes the blockhash policy. -pub use crate::executor::api::execution::ExecutionBlockhashPolicy; +pub use self::execution::ExApiExecutionBlockhashPolicy; /// Exposes the exact execution capability result. -pub use crate::executor::api::execution::ExecutionCapability; +pub use self::execution::ExApiExecutionCapability; /// Exposes supported Solana clusters. -pub use crate::executor::api::execution::ExecutionCluster; +pub use self::execution::ExApiExecutionCluster; /// Exposes cluster restrictions. -pub use crate::executor::api::execution::ExecutionClusterPolicy; +pub use self::execution::ExApiExecutionClusterPolicy; /// Exposes the result of waiting for transaction confirmation. -pub use crate::executor::api::execution::ExecutionConfirmationResult; +pub use self::execution::ExApiExecutionConfirmationResult; /// Exposes transaction confirmation states. -pub use crate::executor::api::execution::ExecutionConfirmationStatus; +pub use self::execution::ExApiExecutionConfirmationStatus; /// Exposes explicit execution cost ceilings. -pub use crate::executor::api::execution::ExecutionCostLimit; +pub use self::execution::ExApiExecutionCostLimit; /// Exposes the complete execution policy. -pub use crate::executor::api::execution::ExecutionPolicy; +pub use self::execution::ExApiExecutionPolicy; /// Exposes the result of a transaction send adapter. -pub use crate::executor::api::execution::ExecutionSendResult; +pub use self::execution::ExApiExecutionSendResult; /// Exposes the simulation policy. -pub use crate::executor::api::execution::ExecutionSimulationPolicy; +pub use self::execution::ExApiExecutionSimulationPolicy; /// Exposes the simulation result contract. -pub use crate::executor::api::execution::ExecutionSimulationResult; +pub use self::execution::ExApiExecutionSimulationResult; /// Exposes one planned instruction account. -pub use crate::executor::api::execution::PlannedAccount; +pub use self::execution::ExApiPlannedAccount; /// Exposes one encoded planned instruction. -pub use crate::executor::api::execution::PlannedInstruction; +pub use self::execution::ExApiPlannedInstruction; /// Exposes post-execution replay diagnostics. -pub use crate::executor::api::execution::PostExecutionDiagnostic; +pub use self::execution::ExApiPostExecutionDiagnostic; /// Exposes post-execution validation requirements. -pub use crate::executor::api::execution::PostExecutionValidationPolicy; +pub use self::execution::ExApiPostExecutionValidationPolicy; /// Exposes a typed execution plan. -pub use crate::executor::api::execution::PreparedExecutionPlan; +pub use self::execution::ExApiPreparedExecutionPlan; /// Exposes one required signer. -pub use crate::executor::api::execution::RequiredSigner; +pub use self::execution::ExApiRequiredSigner; /// Exposes the typed executor contract. -pub use crate::executor::api::execution::TypedInstructionExecutor; +pub use self::execution::ExApiTypedInstructionExecutor; /// Exposes the legacy common execution plan type. -pub use crate::executor::api::executor::ExecutionPlan; +pub use self::executor::ExApiExecutionPlan; /// Exposes the legacy common execution request type. -pub use crate::executor::api::executor::ExecutionRequest; +pub use self::executor::ExApiExecutionRequest; /// Exposes the legacy common execution support enum. -pub use crate::executor::api::executor::ExecutionSupport; +pub use self::executor::ExApiExecutionSupport; /// Exposes the legacy common instruction executor trait. -pub use crate::executor::api::executor::InstructionExecutor; +pub use self::executor::ExApiInstructionExecutor; /// Exposes the compact JSON payload serializer. -pub use crate::executor::api::executor::serialize_payload_json; +pub use self::executor::executor_api_serialize_payload_json; /// Exposes the pretty JSON payload serializer. -pub use crate::executor::api::executor::serialize_payload_json_pretty; +pub use self::executor::executor_api_serialize_payload_json_pretty; diff --git a/kb-lib/src/executor/api/execution.rs b/kb-lib/src/executor/api/execution.rs index 74b329a..2da6272 100644 --- a/kb-lib/src/executor/api/execution.rs +++ b/kb-lib/src/executor/api/execution.rs @@ -12,7 +12,7 @@ use ts_rs::TS; // rust-rules: derive-import export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionCapability.ts" )] -pub enum ExecutionCapability { +pub enum ExApiExecutionCapability { /// The operation is implemented by the executor. Supported { /// Stable operation code implemented by the executor. @@ -27,7 +27,7 @@ pub enum ExecutionCapability { }, } -impl crate::ExecutionCapability { +impl crate::ExApiExecutionCapability { /// Creates a supported capability value. pub fn supported(operation_code: impl std::convert::Into) -> Self { return Self::Supported { operation_code: operation_code.into() }; @@ -57,7 +57,7 @@ impl crate::ExecutionCapability { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionCluster.ts" )] -pub enum ExecutionCluster { +pub enum ExApiExecutionCluster { /// Local validator cluster. Localnet, /// Public development cluster. @@ -80,7 +80,7 @@ enum ExecutionClusterWire { Mainnet, } -impl<'de> serde::Deserialize<'de> for crate::ExecutionCluster { +impl<'de> serde::Deserialize<'de> for crate::ExApiExecutionCluster { fn deserialize( deserializer: Deserializer, ) -> std::result::Result @@ -106,19 +106,19 @@ impl<'de> serde::Deserialize<'de> for crate::ExecutionCluster { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionClusterPolicy.ts" )] -pub struct ExecutionClusterPolicy { +pub struct ExApiExecutionClusterPolicy { /// Cluster that the RPC endpoint must report. - pub expected_cluster: crate::ExecutionCluster, + pub expected_cluster: crate::ExApiExecutionCluster, /// Whether production execution may proceed after all other checks. pub allow_mainnet: bool, /// Whether the operator explicitly confirmed this production execution. pub mainnet_confirmation: bool, } -impl std::default::Default for crate::ExecutionClusterPolicy { +impl std::default::Default for crate::ExApiExecutionClusterPolicy { fn default() -> Self { return Self { - expected_cluster: crate::ExecutionCluster::Devnet, + expected_cluster: crate::ExApiExecutionCluster::Devnet, allow_mainnet: false, mainnet_confirmation: false, }; @@ -132,7 +132,7 @@ impl std::default::Default for crate::ExecutionClusterPolicy { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionSimulationPolicy.ts" )] -pub enum ExecutionSimulationPolicy { +pub enum ExApiExecutionSimulationPolicy { /// Simulation must succeed before signing or sending. Required, /// Simulation is not required. Safety policy rejects this mode by default. @@ -146,7 +146,7 @@ pub enum ExecutionSimulationPolicy { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionBlockhashKind.ts" )] -pub enum ExecutionBlockhashKind { +pub enum ExApiExecutionBlockhashKind { /// Fetch a recent blockhash and enforce a bounded age. Latest, /// Use a durable nonce account and authority. @@ -159,21 +159,21 @@ pub enum ExecutionBlockhashKind { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionBlockhashPolicy.ts" )] -pub struct ExecutionBlockhashPolicy { +pub struct ExApiExecutionBlockhashPolicy { /// Selected blockhash source. - pub kind: crate::ExecutionBlockhashKind, + pub kind: crate::ExApiExecutionBlockhashKind, /// Maximum accepted age for a recent blockhash, in slots. pub max_age_slots: std::option::Option, /// Durable nonce account when `kind` is `DurableNonce`. - pub nonce_account: std::option::Option, + pub nonce_account: std::option::Option, /// Durable nonce authority when `kind` is `DurableNonce`. - pub nonce_authority: std::option::Option, + pub nonce_authority: std::option::Option, } -impl std::default::Default for crate::ExecutionBlockhashPolicy { +impl std::default::Default for crate::ExApiExecutionBlockhashPolicy { fn default() -> Self { return Self { - kind: crate::ExecutionBlockhashKind::Latest, + kind: crate::ExApiExecutionBlockhashKind::Latest, max_age_slots: std::option::Option::Some(150), nonce_account: std::option::Option::None, nonce_authority: std::option::Option::None, @@ -187,7 +187,7 @@ impl std::default::Default for crate::ExecutionBlockhashPolicy { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionCostLimit.ts" )] -pub struct ExecutionCostLimit { +pub struct ExApiExecutionCostLimit { /// Maximum lamports that operation instructions may transfer or lock. pub max_spend_lamports: std::option::Option, /// Maximum total transaction fee accepted after simulation. @@ -196,7 +196,7 @@ pub struct ExecutionCostLimit { pub max_compute_unit_price_micro_lamports: std::option::Option, } -impl std::default::Default for crate::ExecutionCostLimit { +impl std::default::Default for crate::ExApiExecutionCostLimit { fn default() -> Self { return Self { max_spend_lamports: std::option::Option::None, @@ -212,7 +212,7 @@ impl std::default::Default for crate::ExecutionCostLimit { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/PostExecutionValidationPolicy.ts" )] -pub struct PostExecutionValidationPolicy { +pub struct ExApiPostExecutionValidationPolicy { /// Whether the sent signature must be inserted into canonical storage. pub canonical_insert_required: bool, /// Whether core extraction must complete. @@ -223,7 +223,7 @@ pub struct PostExecutionValidationPolicy { pub materialization_required: bool, } -impl std::default::Default for crate::PostExecutionValidationPolicy { +impl std::default::Default for crate::ExApiPostExecutionValidationPolicy { fn default() -> Self { return Self { canonical_insert_required: true, @@ -240,33 +240,33 @@ impl std::default::Default for crate::PostExecutionValidationPolicy { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionPolicy.ts" )] -pub struct ExecutionPolicy { +pub struct ExApiExecutionPolicy { /// Cluster restrictions. - pub cluster: crate::ExecutionClusterPolicy, + pub cluster: crate::ExApiExecutionClusterPolicy, /// Simulation requirement. - pub simulation: crate::ExecutionSimulationPolicy, + pub simulation: crate::ExApiExecutionSimulationPolicy, /// Blockhash source restrictions. - pub blockhash: crate::ExecutionBlockhashPolicy, + pub blockhash: crate::ExApiExecutionBlockhashPolicy, /// Explicit operation and fee ceilings. - pub cost_limit: crate::ExecutionCostLimit, + pub cost_limit: crate::ExApiExecutionCostLimit, /// Public keys authorized to sign this plan. - pub authorized_signers: std::vec::Vec, + pub authorized_signers: std::vec::Vec, /// Whether the operation is restricted to plan construction and simulation. pub dry_run: bool, /// Required post-execution validation steps. - pub post_execution_validation: crate::PostExecutionValidationPolicy, + pub post_execution_validation: crate::ExApiPostExecutionValidationPolicy, } -impl std::default::Default for crate::ExecutionPolicy { +impl std::default::Default for crate::ExApiExecutionPolicy { fn default() -> Self { return Self { - cluster: crate::ExecutionClusterPolicy::default(), - simulation: crate::ExecutionSimulationPolicy::Required, - blockhash: crate::ExecutionBlockhashPolicy::default(), - cost_limit: crate::ExecutionCostLimit::default(), + cluster: crate::ExApiExecutionClusterPolicy::default(), + simulation: crate::ExApiExecutionSimulationPolicy::Required, + blockhash: crate::ExApiExecutionBlockhashPolicy::default(), + cost_limit: crate::ExApiExecutionCostLimit::default(), authorized_signers: std::vec::Vec::new(), dry_run: true, - post_execution_validation: crate::PostExecutionValidationPolicy::default(), + post_execution_validation: crate::ExApiPostExecutionValidationPolicy::default(), }; } } @@ -277,9 +277,9 @@ impl std::default::Default for crate::ExecutionPolicy { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/PlannedAccount.ts" )] -pub struct PlannedAccount { +pub struct ExApiPlannedAccount { /// Account public key. - pub pubkey: crate::Pubkey, + pub pubkey: crate::MdPubkey, /// Whether the account must sign the transaction. pub is_signer: bool, /// Whether the account must be writable. @@ -292,13 +292,13 @@ pub struct PlannedAccount { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/PlannedInstruction.ts" )] -pub struct PlannedInstruction { +pub struct ExApiPlannedInstruction { /// Target program id. - pub program_id: crate::ProgramId, + pub program_id: crate::MdProgramId, /// Stable operation code represented by the instruction. pub operation_code: std::string::String, /// Ordered account metadata. - pub accounts: std::vec::Vec, + pub accounts: std::vec::Vec, /// Exact encoded instruction payload. pub data: std::vec::Vec, } @@ -309,9 +309,9 @@ pub struct PlannedInstruction { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/RequiredSigner.ts" )] -pub struct RequiredSigner { +pub struct ExApiRequiredSigner { /// Signer public key. - pub pubkey: crate::Pubkey, + pub pubkey: crate::MdPubkey, /// Stable signer role such as `fee_payer`, `funding_account` or `new_account`. pub role: std::string::String, } @@ -322,7 +322,7 @@ pub struct RequiredSigner { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/PreparedExecutionPlan.ts" )] -pub struct PreparedExecutionPlan { +pub struct ExApiPreparedExecutionPlan { /// Stable executor crate name. pub executor_name: std::string::String, /// Executor package version. @@ -332,13 +332,13 @@ pub struct PreparedExecutionPlan { /// Stable operation code. pub operation_code: std::string::String, /// Transaction fee payer. - pub fee_payer: crate::Pubkey, + pub fee_payer: crate::MdPubkey, /// Ordered instructions to place in the transaction message. - pub instructions: std::vec::Vec, + pub instructions: std::vec::Vec, /// Deduplicated signers required by the fee payer and instruction metas. - pub required_signers: std::vec::Vec, + pub required_signers: std::vec::Vec, /// Explicit policy to evaluate before simulation, signing and sending. - pub policy: crate::ExecutionPolicy, + pub policy: crate::ExApiExecutionPolicy, /// Lamports explicitly transferred or locked by planned instructions. pub requested_spend_lamports: u64, /// Requested compute-unit price, when present. @@ -351,15 +351,15 @@ pub struct PreparedExecutionPlan { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionSimulationResult.ts" )] -pub struct ExecutionSimulationResult { +pub struct ExApiExecutionSimulationResult { /// Whether an RPC simulation call was actually performed. pub simulated: bool, /// Whether the simulated transaction completed successfully. pub success: bool, /// Cluster reported by the simulation adapter. - pub cluster: crate::ExecutionCluster, + pub cluster: crate::ExApiExecutionCluster, /// Blockhash source used by the simulated transaction. - pub blockhash_kind: crate::ExecutionBlockhashKind, + pub blockhash_kind: crate::ExApiExecutionBlockhashKind, /// Observed recent blockhash age, in slots. pub blockhash_age_slots: std::option::Option, /// Replacement blockhash returned by the node, if replacement was requested. @@ -369,9 +369,9 @@ pub struct ExecutionSimulationResult { #[serde(default)] pub replacement_last_valid_block_height: std::option::Option, /// Durable nonce account used by the simulated transaction. - pub nonce_account: std::option::Option, + pub nonce_account: std::option::Option, /// Durable nonce authority used by the simulated transaction. - pub nonce_authority: std::option::Option, + pub nonce_authority: std::option::Option, /// Compute units consumed when reported by the RPC endpoint. pub units_consumed: std::option::Option, /// Estimated transaction fee in lamports when available. @@ -388,11 +388,11 @@ pub struct ExecutionSimulationResult { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionSendResult.ts" )] -pub struct ExecutionSendResult { +pub struct ExApiExecutionSendResult { /// Cluster used for submission. - pub cluster: crate::ExecutionCluster, + pub cluster: crate::ExApiExecutionCluster, /// Signature returned by the RPC endpoint. - pub signature: crate::Signature, + pub signature: crate::MdSignature, /// Whether submission was accepted by the RPC endpoint. pub submitted: bool, } @@ -404,7 +404,7 @@ pub struct ExecutionSendResult { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionConfirmationStatus.ts" )] -pub enum ExecutionConfirmationStatus { +pub enum ExApiExecutionConfirmationStatus { /// The transaction was observed at processed commitment. Processed, /// The transaction reached confirmed commitment. @@ -425,13 +425,13 @@ pub enum ExecutionConfirmationStatus { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/ExecutionConfirmationResult.ts" )] -pub struct ExecutionConfirmationResult { +pub struct ExApiExecutionConfirmationResult { /// Cluster queried for confirmation. - pub cluster: crate::ExecutionCluster, + pub cluster: crate::ExApiExecutionCluster, /// Submitted transaction signature. - pub signature: crate::Signature, + pub signature: crate::MdSignature, /// Highest confirmation state reached. - pub status: crate::ExecutionConfirmationStatus, + pub status: crate::ExApiExecutionConfirmationStatus, /// Slot that reported the transaction when available. pub slot: std::option::Option, /// Number of status polling attempts performed. @@ -448,9 +448,9 @@ pub struct ExecutionConfirmationResult { export, export_to = "../frontend/ts/bindings/kb_execution_api/execution/PostExecutionDiagnostic.ts" )] -pub struct PostExecutionDiagnostic { +pub struct ExApiPostExecutionDiagnostic { /// Executed transaction signature. - pub signature: crate::Signature, + pub signature: crate::MdSignature, /// Whether canonical insertion completed. pub canonical_inserted: bool, /// Whether core extraction completed. @@ -464,33 +464,33 @@ pub struct PostExecutionDiagnostic { } /// Contract implemented by executors that expose typed intents and exact plans. -pub trait TypedInstructionExecutor { +pub trait ExApiTypedInstructionExecutor { /// Protocol-specific typed intent. type Intent; /// Returns the exact capability for one program and operation code. fn capability( &self, - program_id: &crate::ProgramId, + program_id: &crate::MdProgramId, operation_code: &str, - ) -> crate::ExecutionCapability; + ) -> crate::ExApiExecutionCapability; /// Builds a typed execution plan without signing, sending or performing I/O. fn build_prepared_plan( &self, intent: &Self::Intent, - ) -> kb_core::Result; + ) -> kb_core::Result; } #[cfg(test)] mod tests { #[test] fn mainnet_cluster_serializes_with_current_name() { - let serialized = serde_json::to_string(&crate::ExecutionCluster::Mainnet) + let serialized = serde_json::to_string(&crate::ExApiExecutionCluster::Mainnet) .unwrap_or_else(|error| panic!("unexpected serialization error: {error}")); assert_eq!(serialized, "\"mainnet\""); - let legacy = serde_json::from_str::("\"mainnet_beta\"") + let legacy = serde_json::from_str::("\"mainnet_beta\"") .unwrap_or_else(|error| panic!("unexpected deserialization error: {error}")); - assert_eq!(legacy, crate::ExecutionCluster::Mainnet); + assert_eq!(legacy, crate::ExApiExecutionCluster::Mainnet); } } diff --git a/kb-lib/src/executor/api/executor.rs b/kb-lib/src/executor/api/executor.rs index 499ce59..39c043f 100644 --- a/kb-lib/src/executor/api/executor.rs +++ b/kb-lib/src/executor/api/executor.rs @@ -11,7 +11,7 @@ use ts_rs::TS; // rust-rules: derive-import export, export_to = "../frontend/ts/bindings/kb_execution_api/executor/ExecutionSupport.ts" )] -pub enum ExecutionSupport { +pub enum ExApiExecutionSupport { /// The executor cannot handle the request. No, /// The executor may handle the request after account and payload validation. @@ -26,9 +26,9 @@ pub enum ExecutionSupport { export, export_to = "../frontend/ts/bindings/kb_execution_api/executor/ExecutionRequest.ts" )] -pub struct ExecutionRequest { +pub struct ExApiExecutionRequest { /// Target program id. - pub program_id: crate::ProgramId, + pub program_id: crate::MdProgramId, /// Stable operation code such as buy, sell, transfer or route. pub operation_code: std::string::String, /// Serialized JSON payload reserved for protocol-specific arguments. @@ -41,7 +41,7 @@ pub struct ExecutionRequest { export, export_to = "../frontend/ts/bindings/kb_execution_api/executor/ExecutionPlan.ts" )] -pub struct ExecutionPlan { +pub struct ExApiExecutionPlan { /// Stable executor crate name. pub executor_name: std::string::String, /// Number of instructions that would be produced by the final implementation. @@ -51,7 +51,9 @@ pub struct ExecutionPlan { } /// Serializes a JSON payload to its compact string representation. -pub fn serialize_payload_json(value: &serde_json::Value) -> kb_core::Result { +pub fn executor_api_serialize_payload_json( + value: &serde_json::Value, +) -> kb_core::Result { return match serde_json::to_string(value) { std::result::Result::Ok(serialized) => std::result::Result::Ok(serialized), std::result::Result::Err(error) => std::result::Result::Err(kb_core::Error::new( @@ -62,7 +64,7 @@ pub fn serialize_payload_json(value: &serde_json::Value) -> kb_core::Result kb_core::Result { return match serde_json::to_string_pretty(value) { @@ -75,7 +77,7 @@ pub fn serialize_payload_json_pretty( } /// Common contract implemented by all execution crates. -pub trait InstructionExecutor { +pub trait ExApiInstructionExecutor { /// Returns the stable executor name. fn executor_name(&self) -> &'static str; @@ -86,7 +88,7 @@ pub trait InstructionExecutor { fn program_ids(&self) -> &'static [&'static str]; /// Tests whether this executor owns a program id. - fn handles_program_id(&self, program_id: &crate::ProgramId) -> bool { + fn handles_program_id(&self, program_id: &crate::MdProgramId) -> bool { return self .program_ids() .iter() @@ -94,11 +96,14 @@ pub trait InstructionExecutor { } /// Tests whether this executor supports a request. - fn supports_request(&self, request: &crate::ExecutionRequest) -> crate::ExecutionSupport; + fn supports_request( + &self, + request: &crate::ExApiExecutionRequest, + ) -> crate::ExApiExecutionSupport; /// Builds a neutral execution plan placeholder. fn build_plan( &self, - request: &crate::ExecutionRequest, - ) -> kb_core::Result; + request: &crate::ExApiExecutionRequest, + ) -> kb_core::Result; } diff --git a/kb-lib/src/executor/bridge.rs b/kb-lib/src/executor/bridge.rs index a7318eb..08c5b84 100644 --- a/kb-lib/src/executor/bridge.rs +++ b/kb-lib/src/executor/bridge.rs @@ -3,7 +3,7 @@ //! `bridge` executor family. -pub mod circle_cctp_token_messenger_minter; -pub mod circle_cctp_token_messenger_minter_v2; -pub mod layer_zero_endpoint; -pub mod layer_zero_executor; +mod circle_cctp_token_messenger_minter; +mod circle_cctp_token_messenger_minter_v2; +mod layer_zero_endpoint; +mod layer_zero_executor; diff --git a/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter.rs b/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter.rs index fde20ef..2ebf2fa 100644 --- a/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter.rs +++ b/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_bridge_circle_cctp_token_messenger_minter`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_bridge_circle_cctp_token_messenger_minter"; +const LEGACY_CRATE: &str = "kb_executor_bridge_circle_cctp_token_messenger_minter"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter_v2.rs b/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter_v2.rs index b30dcc7..361c61d 100644 --- a/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter_v2.rs +++ b/kb-lib/src/executor/bridge/circle_cctp_token_messenger_minter_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_bridge_circle_cctp_token_messenger_minter_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_bridge_circle_cctp_token_messenger_minter_v2"; +const LEGACY_CRATE: &str = "kb_executor_bridge_circle_cctp_token_messenger_minter_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/bridge/layer_zero_endpoint.rs b/kb-lib/src/executor/bridge/layer_zero_endpoint.rs index d25f62f..25cea74 100644 --- a/kb-lib/src/executor/bridge/layer_zero_endpoint.rs +++ b/kb-lib/src/executor/bridge/layer_zero_endpoint.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_bridge_layer_zero_endpoint`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_bridge_layer_zero_endpoint"; +const LEGACY_CRATE: &str = "kb_executor_bridge_layer_zero_endpoint"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/bridge/layer_zero_executor.rs b/kb-lib/src/executor/bridge/layer_zero_executor.rs index be521ae..a13dfe1 100644 --- a/kb-lib/src/executor/bridge/layer_zero_executor.rs +++ b/kb-lib/src/executor/bridge/layer_zero_executor.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_bridge_layer_zero_executor`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_bridge_layer_zero_executor"; +const LEGACY_CRATE: &str = "kb_executor_bridge_layer_zero_executor"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/clmm.rs b/kb-lib/src/executor/clmm.rs index 10e30be..9afb745 100644 --- a/kb-lib/src/executor/clmm.rs +++ b/kb-lib/src/executor/clmm.rs @@ -3,9 +3,9 @@ //! `clmm` executor family. -pub mod byreal; -pub mod fusion; -pub mod orca_whirlpool; -pub mod pancake_swap; -pub mod raydium; -pub mod stabble; +mod byreal; +mod fusion; +mod orca_whirlpool; +mod pancake_swap; +mod raydium; +mod stabble; diff --git a/kb-lib/src/executor/clmm/byreal.rs b/kb-lib/src/executor/clmm/byreal.rs index 474a272..a9c803a 100644 --- a/kb-lib/src/executor/clmm/byreal.rs +++ b/kb-lib/src/executor/clmm/byreal.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_clmm_byreal`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_clmm_byreal"; +const LEGACY_CRATE: &str = "kb_executor_clmm_byreal"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/clmm/fusion.rs b/kb-lib/src/executor/clmm/fusion.rs index b4372c9..987f0db 100644 --- a/kb-lib/src/executor/clmm/fusion.rs +++ b/kb-lib/src/executor/clmm/fusion.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_clmm_fusion`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_clmm_fusion"; +const LEGACY_CRATE: &str = "kb_executor_clmm_fusion"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/clmm/orca_whirlpool.rs b/kb-lib/src/executor/clmm/orca_whirlpool.rs index e928020..86f809c 100644 --- a/kb-lib/src/executor/clmm/orca_whirlpool.rs +++ b/kb-lib/src/executor/clmm/orca_whirlpool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_clmm_orca_whirlpool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_clmm_orca_whirlpool"; +const LEGACY_CRATE: &str = "kb_executor_clmm_orca_whirlpool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/clmm/pancake_swap.rs b/kb-lib/src/executor/clmm/pancake_swap.rs index 6597e32..f998ccc 100644 --- a/kb-lib/src/executor/clmm/pancake_swap.rs +++ b/kb-lib/src/executor/clmm/pancake_swap.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_clmm_pancake_swap`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_clmm_pancake_swap"; +const LEGACY_CRATE: &str = "kb_executor_clmm_pancake_swap"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/clmm/raydium.rs b/kb-lib/src/executor/clmm/raydium.rs index cbcafc3..5ea34d7 100644 --- a/kb-lib/src/executor/clmm/raydium.rs +++ b/kb-lib/src/executor/clmm/raydium.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_clmm_raydium`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_clmm_raydium"; +const LEGACY_CRATE: &str = "kb_executor_clmm_raydium"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/clmm/stabble.rs b/kb-lib/src/executor/clmm/stabble.rs index 9e7ef93..3640bbf 100644 --- a/kb-lib/src/executor/clmm/stabble.rs +++ b/kb-lib/src/executor/clmm/stabble.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_clmm_stabble`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_clmm_stabble"; +const LEGACY_CRATE: &str = "kb_executor_clmm_stabble"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/cpmm.rs b/kb-lib/src/executor/cpmm.rs index b478176..d1913c8 100644 --- a/kb-lib/src/executor/cpmm.rs +++ b/kb-lib/src/executor/cpmm.rs @@ -3,4 +3,4 @@ //! `cpmm` executor family. -pub mod raydium; +mod raydium; diff --git a/kb-lib/src/executor/cpmm/raydium.rs b/kb-lib/src/executor/cpmm/raydium.rs index ec33d26..be53c43 100644 --- a/kb-lib/src/executor/cpmm/raydium.rs +++ b/kb-lib/src/executor/cpmm/raydium.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_cpmm_raydium`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_cpmm_raydium"; +const LEGACY_CRATE: &str = "kb_executor_cpmm_raydium"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/dlmm.rs b/kb-lib/src/executor/dlmm.rs index be1c1b3..b32fba1 100644 --- a/kb-lib/src/executor/dlmm.rs +++ b/kb-lib/src/executor/dlmm.rs @@ -3,4 +3,4 @@ //! `dlmm` executor family. -pub mod meteora; +mod meteora; diff --git a/kb-lib/src/executor/dlmm/meteora.rs b/kb-lib/src/executor/dlmm/meteora.rs index f0ec784..9b7e7e4 100644 --- a/kb-lib/src/executor/dlmm/meteora.rs +++ b/kb-lib/src/executor/dlmm/meteora.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_dlmm_meteora`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_dlmm_meteora"; +const LEGACY_CRATE: &str = "kb_executor_dlmm_meteora"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/fees.rs b/kb-lib/src/executor/fees.rs index 52be93c..ad9c4c1 100644 --- a/kb-lib/src/executor/fees.rs +++ b/kb-lib/src/executor/fees.rs @@ -3,5 +3,5 @@ //! `fees` executor family. -pub mod bags_fee_share_v1; -pub mod bags_fee_share_v2; +mod bags_fee_share_v1; +mod bags_fee_share_v2; diff --git a/kb-lib/src/executor/fees/bags_fee_share_v1.rs b/kb-lib/src/executor/fees/bags_fee_share_v1.rs index 0a4b259..c8939ce 100644 --- a/kb-lib/src/executor/fees/bags_fee_share_v1.rs +++ b/kb-lib/src/executor/fees/bags_fee_share_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_fees_bags_fee_share_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_fees_bags_fee_share_v1"; +const LEGACY_CRATE: &str = "kb_executor_fees_bags_fee_share_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/fees/bags_fee_share_v2.rs b/kb-lib/src/executor/fees/bags_fee_share_v2.rs index 1dbed37..6053f84 100644 --- a/kb-lib/src/executor/fees/bags_fee_share_v2.rs +++ b/kb-lib/src/executor/fees/bags_fee_share_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_fees_bags_fee_share_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_fees_bags_fee_share_v2"; +const LEGACY_CRATE: &str = "kb_executor_fees_bags_fee_share_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/governance.rs b/kb-lib/src/executor/governance.rs index f570307..ee48869 100644 --- a/kb-lib/src/executor/governance.rs +++ b/kb-lib/src/executor/governance.rs @@ -3,4 +3,4 @@ //! `governance` executor family. -pub mod metadao_bid_wall; +mod metadao_bid_wall; diff --git a/kb-lib/src/executor/governance/metadao_bid_wall.rs b/kb-lib/src/executor/governance/metadao_bid_wall.rs index 7ca7ecf..420b2f8 100644 --- a/kb-lib/src/executor/governance/metadao_bid_wall.rs +++ b/kb-lib/src/executor/governance/metadao_bid_wall.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_governance_metadao_bid_wall`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_governance_metadao_bid_wall"; +const LEGACY_CRATE: &str = "kb_executor_governance_metadao_bid_wall"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad.rs b/kb-lib/src/executor/launchpad.rs index bbc2ba3..b4b5b9e 100644 --- a/kb-lib/src/executor/launchpad.rs +++ b/kb-lib/src/executor/launchpad.rs @@ -3,12 +3,12 @@ //! `launchpad` executor family. -pub mod boop_fun; -pub mod metadao_ico; -pub mod meteora_dbc; -pub mod moonit; -pub mod orca_wavebreak; -pub mod printr; -pub mod pump_fun; -pub mod pump_pumpup_ai; -pub mod raydium_launchlab; +mod boop_fun; +mod metadao_ico; +mod meteora_dbc; +mod moonit; +mod orca_wavebreak; +mod printr; +mod pump_fun; +mod pump_pumpup_ai; +mod raydium_launchlab; diff --git a/kb-lib/src/executor/launchpad/boop_fun.rs b/kb-lib/src/executor/launchpad/boop_fun.rs index 6022143..48b240a 100644 --- a/kb-lib/src/executor/launchpad/boop_fun.rs +++ b/kb-lib/src/executor/launchpad/boop_fun.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_boop_fun`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_boop_fun"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_boop_fun"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/metadao_ico.rs b/kb-lib/src/executor/launchpad/metadao_ico.rs index 1a8ef7e..2dccf12 100644 --- a/kb-lib/src/executor/launchpad/metadao_ico.rs +++ b/kb-lib/src/executor/launchpad/metadao_ico.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_metadao_ico`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_metadao_ico"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_metadao_ico"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/meteora_dbc.rs b/kb-lib/src/executor/launchpad/meteora_dbc.rs index bb25599..417eac9 100644 --- a/kb-lib/src/executor/launchpad/meteora_dbc.rs +++ b/kb-lib/src/executor/launchpad/meteora_dbc.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_meteora_dbc`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_meteora_dbc"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_meteora_dbc"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/moonit.rs b/kb-lib/src/executor/launchpad/moonit.rs index e460dd6..ce22f20 100644 --- a/kb-lib/src/executor/launchpad/moonit.rs +++ b/kb-lib/src/executor/launchpad/moonit.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_moonit`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_moonit"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_moonit"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/orca_wavebreak.rs b/kb-lib/src/executor/launchpad/orca_wavebreak.rs index c18acb7..b50d4f3 100644 --- a/kb-lib/src/executor/launchpad/orca_wavebreak.rs +++ b/kb-lib/src/executor/launchpad/orca_wavebreak.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_orca_wavebreak`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_orca_wavebreak"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_orca_wavebreak"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/printr.rs b/kb-lib/src/executor/launchpad/printr.rs index 58db109..d6ca468 100644 --- a/kb-lib/src/executor/launchpad/printr.rs +++ b/kb-lib/src/executor/launchpad/printr.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_printr`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_printr"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_printr"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/pump_fun.rs b/kb-lib/src/executor/launchpad/pump_fun.rs index 39f1bab..4337755 100644 --- a/kb-lib/src/executor/launchpad/pump_fun.rs +++ b/kb-lib/src/executor/launchpad/pump_fun.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_pump_fun`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_pump_fun"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_pump_fun"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/pump_pumpup_ai.rs b/kb-lib/src/executor/launchpad/pump_pumpup_ai.rs index 7e265b8..dcc20d4 100644 --- a/kb-lib/src/executor/launchpad/pump_pumpup_ai.rs +++ b/kb-lib/src/executor/launchpad/pump_pumpup_ai.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_pump_pumpup_ai`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_pump_pumpup_ai"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_pump_pumpup_ai"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/launchpad/raydium_launchlab.rs b/kb-lib/src/executor/launchpad/raydium_launchlab.rs index 3ca77cf..96e2c1e 100644 --- a/kb-lib/src/executor/launchpad/raydium_launchlab.rs +++ b/kb-lib/src/executor/launchpad/raydium_launchlab.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_launchpad_raydium_launchlab`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_launchpad_raydium_launchlab"; +const LEGACY_CRATE: &str = "kb_executor_launchpad_raydium_launchlab"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lending.rs b/kb-lib/src/executor/lending.rs index ef2039a..14e47d0 100644 --- a/kb-lib/src/executor/lending.rs +++ b/kb-lib/src/executor/lending.rs @@ -3,10 +3,10 @@ //! `lending` executor family. -pub mod clone; -pub mod jupiter_lend_borrow; -pub mod jupiter_lend_earn; -pub mod jupiter_lend_flash_loan; -pub mod jupiter_lend_liquidity; -pub mod kamino; -pub mod marginfi_v2; +mod clone; +mod jupiter_lend_borrow; +mod jupiter_lend_earn; +mod jupiter_lend_flash_loan; +mod jupiter_lend_liquidity; +mod kamino; +mod marginfi_v2; diff --git a/kb-lib/src/executor/lending/clone.rs b/kb-lib/src/executor/lending/clone.rs index c65ca42..aeac188 100644 --- a/kb-lib/src/executor/lending/clone.rs +++ b/kb-lib/src/executor/lending/clone.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lending_clone`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lending_clone"; +const LEGACY_CRATE: &str = "kb_executor_lending_clone"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lending/jupiter_lend_borrow.rs b/kb-lib/src/executor/lending/jupiter_lend_borrow.rs index 88ae809..c4ba60e 100644 --- a/kb-lib/src/executor/lending/jupiter_lend_borrow.rs +++ b/kb-lib/src/executor/lending/jupiter_lend_borrow.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lending_jupiter_lend_borrow`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_borrow"; +const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_borrow"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lending/jupiter_lend_earn.rs b/kb-lib/src/executor/lending/jupiter_lend_earn.rs index d617478..18bcfbd 100644 --- a/kb-lib/src/executor/lending/jupiter_lend_earn.rs +++ b/kb-lib/src/executor/lending/jupiter_lend_earn.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lending_jupiter_lend_earn`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_earn"; +const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_earn"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lending/jupiter_lend_flash_loan.rs b/kb-lib/src/executor/lending/jupiter_lend_flash_loan.rs index f63b6e0..9481dac 100644 --- a/kb-lib/src/executor/lending/jupiter_lend_flash_loan.rs +++ b/kb-lib/src/executor/lending/jupiter_lend_flash_loan.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lending_jupiter_lend_flash_loan`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_flash_loan"; +const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_flash_loan"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lending/jupiter_lend_liquidity.rs b/kb-lib/src/executor/lending/jupiter_lend_liquidity.rs index 718ebcb..67b1cc4 100644 --- a/kb-lib/src/executor/lending/jupiter_lend_liquidity.rs +++ b/kb-lib/src/executor/lending/jupiter_lend_liquidity.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lending_jupiter_lend_liquidity`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_liquidity"; +const LEGACY_CRATE: &str = "kb_executor_lending_jupiter_lend_liquidity"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lending/kamino.rs b/kb-lib/src/executor/lending/kamino.rs index 22e777a..139d6dd 100644 --- a/kb-lib/src/executor/lending/kamino.rs +++ b/kb-lib/src/executor/lending/kamino.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lending_kamino`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lending_kamino"; +const LEGACY_CRATE: &str = "kb_executor_lending_kamino"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lending/marginfi_v2.rs b/kb-lib/src/executor/lending/marginfi_v2.rs index d50e56f..0cd1d9c 100644 --- a/kb-lib/src/executor/lending/marginfi_v2.rs +++ b/kb-lib/src/executor/lending/marginfi_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lending_marginfi_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lending_marginfi_v2"; +const LEGACY_CRATE: &str = "kb_executor_lending_marginfi_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/lock.rs b/kb-lib/src/executor/lock.rs index 6cd3b9c..75953bd 100644 --- a/kb-lib/src/executor/lock.rs +++ b/kb-lib/src/executor/lock.rs @@ -3,4 +3,4 @@ //! `lock` executor family. -pub mod raydium_lp; +mod raydium_lp; diff --git a/kb-lib/src/executor/lock/raydium_lp.rs b/kb-lib/src/executor/lock/raydium_lp.rs index 7819f0e..07f8d88 100644 --- a/kb-lib/src/executor/lock/raydium_lp.rs +++ b/kb-lib/src/executor/lock/raydium_lp.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_lock_raydium_lp`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_lock_raydium_lp"; +const LEGACY_CRATE: &str = "kb_executor_lock_raydium_lp"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/metadata.rs b/kb-lib/src/executor/metadata.rs index a9c6301..38df151 100644 --- a/kb-lib/src/executor/metadata.rs +++ b/kb-lib/src/executor/metadata.rs @@ -3,5 +3,5 @@ //! `metadata` executor family. -pub mod metaplex_token_metadata; -pub mod spl_name_service; +mod metaplex_token_metadata; +mod spl_name_service; diff --git a/kb-lib/src/executor/metadata/metaplex_token_metadata.rs b/kb-lib/src/executor/metadata/metaplex_token_metadata.rs index e6dbc89..3f04199 100644 --- a/kb-lib/src/executor/metadata/metaplex_token_metadata.rs +++ b/kb-lib/src/executor/metadata/metaplex_token_metadata.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_metadata_metaplex_token_metadata`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_metadata_metaplex_token_metadata"; +const LEGACY_CRATE: &str = "kb_executor_metadata_metaplex_token_metadata"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/metadata/spl_name_service.rs b/kb-lib/src/executor/metadata/spl_name_service.rs index b30e226..4319563 100644 --- a/kb-lib/src/executor/metadata/spl_name_service.rs +++ b/kb-lib/src/executor/metadata/spl_name_service.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_metadata_spl_name_service`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_metadata_spl_name_service"; +const LEGACY_CRATE: &str = "kb_executor_metadata_spl_name_service"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/nft.rs b/kb-lib/src/executor/nft.rs index 9c0ad96..925c37e 100644 --- a/kb-lib/src/executor/nft.rs +++ b/kb-lib/src/executor/nft.rs @@ -3,4 +3,4 @@ //! `nft` executor family. -pub mod metaplex_bubblegum; +mod metaplex_bubblegum; diff --git a/kb-lib/src/executor/nft/metaplex_bubblegum.rs b/kb-lib/src/executor/nft/metaplex_bubblegum.rs index c44f26b..227f334 100644 --- a/kb-lib/src/executor/nft/metaplex_bubblegum.rs +++ b/kb-lib/src/executor/nft/metaplex_bubblegum.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_nft_metaplex_bubblegum`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_nft_metaplex_bubblegum"; +const LEGACY_CRATE: &str = "kb_executor_nft_metaplex_bubblegum"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/orderbook.rs b/kb-lib/src/executor/orderbook.rs index 54fa55d..248388a 100644 --- a/kb-lib/src/executor/orderbook.rs +++ b/kb-lib/src/executor/orderbook.rs @@ -3,6 +3,6 @@ //! `orderbook` executor family. -pub mod jupiter_limit_order; -pub mod jupiter_limit_order_v2; -pub mod openbook_v2; +mod jupiter_limit_order; +mod jupiter_limit_order_v2; +mod openbook_v2; diff --git a/kb-lib/src/executor/orderbook/jupiter_limit_order.rs b/kb-lib/src/executor/orderbook/jupiter_limit_order.rs index ab3f427..02eda6c 100644 --- a/kb-lib/src/executor/orderbook/jupiter_limit_order.rs +++ b/kb-lib/src/executor/orderbook/jupiter_limit_order.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_orderbook_jupiter_limit_order`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_orderbook_jupiter_limit_order"; +const LEGACY_CRATE: &str = "kb_executor_orderbook_jupiter_limit_order"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/orderbook/jupiter_limit_order_v2.rs b/kb-lib/src/executor/orderbook/jupiter_limit_order_v2.rs index a7de10b..f7a7980 100644 --- a/kb-lib/src/executor/orderbook/jupiter_limit_order_v2.rs +++ b/kb-lib/src/executor/orderbook/jupiter_limit_order_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_orderbook_jupiter_limit_order_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_orderbook_jupiter_limit_order_v2"; +const LEGACY_CRATE: &str = "kb_executor_orderbook_jupiter_limit_order_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/orderbook/openbook_v2.rs b/kb-lib/src/executor/orderbook/openbook_v2.rs index c1ec67c..b56fd80 100644 --- a/kb-lib/src/executor/orderbook/openbook_v2.rs +++ b/kb-lib/src/executor/orderbook/openbook_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_orderbook_openbook_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_orderbook_openbook_v2"; +const LEGACY_CRATE: &str = "kb_executor_orderbook_openbook_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/perpetuals.rs b/kb-lib/src/executor/perpetuals.rs index 5695fc7..f7586fa 100644 --- a/kb-lib/src/executor/perpetuals.rs +++ b/kb-lib/src/executor/perpetuals.rs @@ -3,6 +3,6 @@ //! `perpetuals` executor family. -pub mod drift_v2; -pub mod jupiter; -pub mod zeta; +mod drift_v2; +mod jupiter; +mod zeta; diff --git a/kb-lib/src/executor/perpetuals/drift_v2.rs b/kb-lib/src/executor/perpetuals/drift_v2.rs index fd40831..5e533ad 100644 --- a/kb-lib/src/executor/perpetuals/drift_v2.rs +++ b/kb-lib/src/executor/perpetuals/drift_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_perpetuals_drift_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_perpetuals_drift_v2"; +const LEGACY_CRATE: &str = "kb_executor_perpetuals_drift_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/perpetuals/jupiter.rs b/kb-lib/src/executor/perpetuals/jupiter.rs index d9933ff..29c0eeb 100644 --- a/kb-lib/src/executor/perpetuals/jupiter.rs +++ b/kb-lib/src/executor/perpetuals/jupiter.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_perpetuals_jupiter`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_perpetuals_jupiter"; +const LEGACY_CRATE: &str = "kb_executor_perpetuals_jupiter"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/perpetuals/zeta.rs b/kb-lib/src/executor/perpetuals/zeta.rs index 40ec751..e877665 100644 --- a/kb-lib/src/executor/perpetuals/zeta.rs +++ b/kb-lib/src/executor/perpetuals/zeta.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_perpetuals_zeta`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_perpetuals_zeta"; +const LEGACY_CRATE: &str = "kb_executor_perpetuals_zeta"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/router.rs b/kb-lib/src/executor/router.rs index 7f7c883..063d3f9 100644 --- a/kb-lib/src/executor/router.rs +++ b/kb-lib/src/executor/router.rs @@ -3,9 +3,9 @@ //! `router` executor family. -pub mod dflow_aggregator_v4; -pub mod jupiter_aggregator_v4; -pub mod jupiter_aggregator_v6; -pub mod jupiter_dca; -pub mod okx_labs_v1; -pub mod okx_labs_v2; +mod dflow_aggregator_v4; +mod jupiter_aggregator_v4; +mod jupiter_aggregator_v6; +mod jupiter_dca; +mod okx_labs_v1; +mod okx_labs_v2; diff --git a/kb-lib/src/executor/router/dflow_aggregator_v4.rs b/kb-lib/src/executor/router/dflow_aggregator_v4.rs index 27f3bda..86c8b6e 100644 --- a/kb-lib/src/executor/router/dflow_aggregator_v4.rs +++ b/kb-lib/src/executor/router/dflow_aggregator_v4.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_router_dflow_aggregator_v4`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_router_dflow_aggregator_v4"; +const LEGACY_CRATE: &str = "kb_executor_router_dflow_aggregator_v4"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/router/jupiter_aggregator_v4.rs b/kb-lib/src/executor/router/jupiter_aggregator_v4.rs index d9cf3ec..ccd3013 100644 --- a/kb-lib/src/executor/router/jupiter_aggregator_v4.rs +++ b/kb-lib/src/executor/router/jupiter_aggregator_v4.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_router_jupiter_aggregator_v4`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_router_jupiter_aggregator_v4"; +const LEGACY_CRATE: &str = "kb_executor_router_jupiter_aggregator_v4"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/router/jupiter_aggregator_v6.rs b/kb-lib/src/executor/router/jupiter_aggregator_v6.rs index fc80545..173b958 100644 --- a/kb-lib/src/executor/router/jupiter_aggregator_v6.rs +++ b/kb-lib/src/executor/router/jupiter_aggregator_v6.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_router_jupiter_aggregator_v6`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_router_jupiter_aggregator_v6"; +const LEGACY_CRATE: &str = "kb_executor_router_jupiter_aggregator_v6"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/router/jupiter_dca.rs b/kb-lib/src/executor/router/jupiter_dca.rs index fc08cfb..6f9024d 100644 --- a/kb-lib/src/executor/router/jupiter_dca.rs +++ b/kb-lib/src/executor/router/jupiter_dca.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_router_jupiter_dca`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_router_jupiter_dca"; +const LEGACY_CRATE: &str = "kb_executor_router_jupiter_dca"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/router/okx_labs_v1.rs b/kb-lib/src/executor/router/okx_labs_v1.rs index dbe5ddf..b5f07c3 100644 --- a/kb-lib/src/executor/router/okx_labs_v1.rs +++ b/kb-lib/src/executor/router/okx_labs_v1.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_router_okx_labs_v1`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_router_okx_labs_v1"; +const LEGACY_CRATE: &str = "kb_executor_router_okx_labs_v1"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/router/okx_labs_v2.rs b/kb-lib/src/executor/router/okx_labs_v2.rs index 5151d15..6fbd9bb 100644 --- a/kb-lib/src/executor/router/okx_labs_v2.rs +++ b/kb-lib/src/executor/router/okx_labs_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_router_okx_labs_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_router_okx_labs_v2"; +const LEGACY_CRATE: &str = "kb_executor_router_okx_labs_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/rwa.rs b/kb-lib/src/executor/rwa.rs index b964b14..9fd3357 100644 --- a/kb-lib/src/executor/rwa.rs +++ b/kb-lib/src/executor/rwa.rs @@ -3,4 +3,4 @@ //! `rwa` executor family. -pub mod ondo_global_markets; +mod ondo_global_markets; diff --git a/kb-lib/src/executor/rwa/ondo_global_markets.rs b/kb-lib/src/executor/rwa/ondo_global_markets.rs index b00f533..504d43f 100644 --- a/kb-lib/src/executor/rwa/ondo_global_markets.rs +++ b/kb-lib/src/executor/rwa/ondo_global_markets.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_rwa_ondo_global_markets`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_rwa_ondo_global_markets"; +const LEGACY_CRATE: &str = "kb_executor_rwa_ondo_global_markets"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/solana.rs b/kb-lib/src/executor/solana.rs index 0b85a08..c164ea1 100644 --- a/kb-lib/src/executor/solana.rs +++ b/kb-lib/src/executor/solana.rs @@ -3,4 +3,4 @@ //! `solana` executor family. -pub mod core; +mod core; diff --git a/kb-lib/src/executor/solana/core.rs b/kb-lib/src/executor/solana/core.rs index ea6ba2a..7e53f98 100644 --- a/kb-lib/src/executor/solana/core.rs +++ b/kb-lib/src/executor/solana/core.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_solana_core`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_solana_core"; +const LEGACY_CRATE: &str = "kb_executor_solana_core"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl.rs b/kb-lib/src/executor/spl.rs index b331ab9..2df3a8f 100644 --- a/kb-lib/src/executor/spl.rs +++ b/kb-lib/src/executor/spl.rs @@ -3,12 +3,12 @@ //! `spl` executor family. -pub mod account_compression; -pub mod associated_token_account; -pub mod elgamal_registry; -pub mod memo; -pub mod noop; -pub mod single_pool; -pub mod stake_pool; -pub mod token; -pub mod token_2022; +mod account_compression; +mod associated_token_account; +mod elgamal_registry; +mod memo; +mod noop; +mod single_pool; +mod stake_pool; +mod token; +mod token2022; diff --git a/kb-lib/src/executor/spl/account_compression.rs b/kb-lib/src/executor/spl/account_compression.rs index 7bb7f10..dc12c17 100644 --- a/kb-lib/src/executor/spl/account_compression.rs +++ b/kb-lib/src/executor/spl/account_compression.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_account_compression`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_account_compression"; +const LEGACY_CRATE: &str = "kb_executor_spl_account_compression"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/associated_token_account.rs b/kb-lib/src/executor/spl/associated_token_account.rs index 937f148..193f657 100644 --- a/kb-lib/src/executor/spl/associated_token_account.rs +++ b/kb-lib/src/executor/spl/associated_token_account.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_associated_token_account`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_associated_token_account"; +const LEGACY_CRATE: &str = "kb_executor_spl_associated_token_account"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/elgamal_registry.rs b/kb-lib/src/executor/spl/elgamal_registry.rs index 9f490ac..b230fcb 100644 --- a/kb-lib/src/executor/spl/elgamal_registry.rs +++ b/kb-lib/src/executor/spl/elgamal_registry.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_elgamal_registry`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_elgamal_registry"; +const LEGACY_CRATE: &str = "kb_executor_spl_elgamal_registry"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/memo.rs b/kb-lib/src/executor/spl/memo.rs index 50aab62..a88265a 100644 --- a/kb-lib/src/executor/spl/memo.rs +++ b/kb-lib/src/executor/spl/memo.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_memo`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_memo"; +const LEGACY_CRATE: &str = "kb_executor_spl_memo"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/noop.rs b/kb-lib/src/executor/spl/noop.rs index c162f17..f3b26d8 100644 --- a/kb-lib/src/executor/spl/noop.rs +++ b/kb-lib/src/executor/spl/noop.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_noop`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_noop"; +const LEGACY_CRATE: &str = "kb_executor_spl_noop"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/single_pool.rs b/kb-lib/src/executor/spl/single_pool.rs index 0087f53..64a715a 100644 --- a/kb-lib/src/executor/spl/single_pool.rs +++ b/kb-lib/src/executor/spl/single_pool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_single_pool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_single_pool"; +const LEGACY_CRATE: &str = "kb_executor_spl_single_pool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/stake_pool.rs b/kb-lib/src/executor/spl/stake_pool.rs index 96a0e24..bea9030 100644 --- a/kb-lib/src/executor/spl/stake_pool.rs +++ b/kb-lib/src/executor/spl/stake_pool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_stake_pool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_stake_pool"; +const LEGACY_CRATE: &str = "kb_executor_spl_stake_pool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/token.rs b/kb-lib/src/executor/spl/token.rs index 868e586..6bde217 100644 --- a/kb-lib/src/executor/spl/token.rs +++ b/kb-lib/src/executor/spl/token.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_spl_token`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_token"; +const LEGACY_CRATE: &str = "kb_executor_spl_token"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/spl/token_2022.rs b/kb-lib/src/executor/spl/token2022.rs similarity index 51% rename from kb-lib/src/executor/spl/token_2022.rs rename to kb-lib/src/executor/spl/token2022.rs index fc839bf..6fa7b37 100644 --- a/kb-lib/src/executor/spl/token_2022.rs +++ b/kb-lib/src/executor/spl/token2022.rs @@ -1,10 +1,10 @@ -// file: kb-lib/src/executor/spl/token_2022.rs +// file: kb-lib/src/executor/spl/token2022.rs // version: 1 //! Migration boundary for legacy crate `kb_executor_spl_token_2022`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_spl_token_2022"; +const LEGACY_CRATE: &str = "kb_executor_spl_token2022"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/stable.rs b/kb-lib/src/executor/stable.rs index f8254a0..0357764 100644 --- a/kb-lib/src/executor/stable.rs +++ b/kb-lib/src/executor/stable.rs @@ -3,7 +3,7 @@ //! `stable` executor family. -pub mod swap_hylo_exchange; -pub mod swap_jupiter_stable; -pub mod swap_numeraire; -pub mod swap_stabble; +mod swap_hylo_exchange; +mod swap_jupiter_stable; +mod swap_numeraire; +mod swap_stabble; diff --git a/kb-lib/src/executor/stable/swap_hylo_exchange.rs b/kb-lib/src/executor/stable/swap_hylo_exchange.rs index 92f7706..9486fc6 100644 --- a/kb-lib/src/executor/stable/swap_hylo_exchange.rs +++ b/kb-lib/src/executor/stable/swap_hylo_exchange.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_stable_swap_hylo_exchange`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_stable_swap_hylo_exchange"; +const LEGACY_CRATE: &str = "kb_executor_stable_swap_hylo_exchange"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/stable/swap_jupiter_stable.rs b/kb-lib/src/executor/stable/swap_jupiter_stable.rs index 81a1b69..56db504 100644 --- a/kb-lib/src/executor/stable/swap_jupiter_stable.rs +++ b/kb-lib/src/executor/stable/swap_jupiter_stable.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_stable_swap_jupiter_stable`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_stable_swap_jupiter_stable"; +const LEGACY_CRATE: &str = "kb_executor_stable_swap_jupiter_stable"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/stable/swap_numeraire.rs b/kb-lib/src/executor/stable/swap_numeraire.rs index 968444e..95afdc6 100644 --- a/kb-lib/src/executor/stable/swap_numeraire.rs +++ b/kb-lib/src/executor/stable/swap_numeraire.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_stable_swap_numeraire`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_stable_swap_numeraire"; +const LEGACY_CRATE: &str = "kb_executor_stable_swap_numeraire"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/stable/swap_stabble.rs b/kb-lib/src/executor/stable/swap_stabble.rs index e0d6023..cb02240 100644 --- a/kb-lib/src/executor/stable/swap_stabble.rs +++ b/kb-lib/src/executor/stable/swap_stabble.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_stable_swap_stabble`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_stable_swap_stabble"; +const LEGACY_CRATE: &str = "kb_executor_stable_swap_stabble"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/staking.rs b/kb-lib/src/executor/staking.rs index 2531085..f48ac3c 100644 --- a/kb-lib/src/executor/staking.rs +++ b/kb-lib/src/executor/staking.rs @@ -3,6 +3,6 @@ //! `staking` executor family. -pub mod kamino_farm; -pub mod marinade_finance; -pub mod solayer; +mod kamino_farm; +mod marinade_finance; +mod solayer; diff --git a/kb-lib/src/executor/staking/kamino_farm.rs b/kb-lib/src/executor/staking/kamino_farm.rs index d0984a4..33c53f4 100644 --- a/kb-lib/src/executor/staking/kamino_farm.rs +++ b/kb-lib/src/executor/staking/kamino_farm.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_staking_kamino_farm`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_staking_kamino_farm"; +const LEGACY_CRATE: &str = "kb_executor_staking_kamino_farm"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/staking/marinade_finance.rs b/kb-lib/src/executor/staking/marinade_finance.rs index 7450d6e..930ef3c 100644 --- a/kb-lib/src/executor/staking/marinade_finance.rs +++ b/kb-lib/src/executor/staking/marinade_finance.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_staking_marinade_finance`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_staking_marinade_finance"; +const LEGACY_CRATE: &str = "kb_executor_staking_marinade_finance"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/staking/solayer.rs b/kb-lib/src/executor/staking/solayer.rs index 49e386e..0d8823b 100644 --- a/kb-lib/src/executor/staking/solayer.rs +++ b/kb-lib/src/executor/staking/solayer.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_staking_solayer`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_staking_solayer"; +const LEGACY_CRATE: &str = "kb_executor_staking_solayer"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/treasury.rs b/kb-lib/src/executor/treasury.rs index 00f22e4..3d62acc 100644 --- a/kb-lib/src/executor/treasury.rs +++ b/kb-lib/src/executor/treasury.rs @@ -3,4 +3,4 @@ //! `treasury` executor family. -pub mod helium_treasury_management; +mod helium_treasury_management; diff --git a/kb-lib/src/executor/treasury/helium_treasury_management.rs b/kb-lib/src/executor/treasury/helium_treasury_management.rs index 75ef644..38bfb25 100644 --- a/kb-lib/src/executor/treasury/helium_treasury_management.rs +++ b/kb-lib/src/executor/treasury/helium_treasury_management.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_treasury_helium_treasury_management`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_treasury_helium_treasury_management"; +const LEGACY_CRATE: &str = "kb_executor_treasury_helium_treasury_management"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/vault.rs b/kb-lib/src/executor/vault.rs index abba931..2603929 100644 --- a/kb-lib/src/executor/vault.rs +++ b/kb-lib/src/executor/vault.rs @@ -3,9 +3,9 @@ //! `vault` executor family. -pub mod carrot_defi; -pub mod hylo_stability_pool; -pub mod kamino; -pub mod kamino_v2; -pub mod kamino_yvaults; -pub mod meteora; +mod carrot_defi; +mod hylo_stability_pool; +mod kamino; +mod kamino_v2; +mod kamino_yvaults; +mod meteora; diff --git a/kb-lib/src/executor/vault/carrot_defi.rs b/kb-lib/src/executor/vault/carrot_defi.rs index 070dd77..58355af 100644 --- a/kb-lib/src/executor/vault/carrot_defi.rs +++ b/kb-lib/src/executor/vault/carrot_defi.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_vault_carrot_defi`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_vault_carrot_defi"; +const LEGACY_CRATE: &str = "kb_executor_vault_carrot_defi"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/vault/hylo_stability_pool.rs b/kb-lib/src/executor/vault/hylo_stability_pool.rs index 98ad890..e6d05f7 100644 --- a/kb-lib/src/executor/vault/hylo_stability_pool.rs +++ b/kb-lib/src/executor/vault/hylo_stability_pool.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_vault_hylo_stability_pool`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_vault_hylo_stability_pool"; +const LEGACY_CRATE: &str = "kb_executor_vault_hylo_stability_pool"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/vault/kamino.rs b/kb-lib/src/executor/vault/kamino.rs index c773b6b..4e2228c 100644 --- a/kb-lib/src/executor/vault/kamino.rs +++ b/kb-lib/src/executor/vault/kamino.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_vault_kamino`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_vault_kamino"; +const LEGACY_CRATE: &str = "kb_executor_vault_kamino"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/vault/kamino_v2.rs b/kb-lib/src/executor/vault/kamino_v2.rs index f8fb6cf..85c94d6 100644 --- a/kb-lib/src/executor/vault/kamino_v2.rs +++ b/kb-lib/src/executor/vault/kamino_v2.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_vault_kamino_v2`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_vault_kamino_v2"; +const LEGACY_CRATE: &str = "kb_executor_vault_kamino_v2"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/vault/kamino_yvaults.rs b/kb-lib/src/executor/vault/kamino_yvaults.rs index 5c1acd4..05d47c2 100644 --- a/kb-lib/src/executor/vault/kamino_yvaults.rs +++ b/kb-lib/src/executor/vault/kamino_yvaults.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_vault_kamino_yvaults`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_vault_kamino_yvaults"; +const LEGACY_CRATE: &str = "kb_executor_vault_kamino_yvaults"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/vault/meteora.rs b/kb-lib/src/executor/vault/meteora.rs index 4510a87..3eec4c9 100644 --- a/kb-lib/src/executor/vault/meteora.rs +++ b/kb-lib/src/executor/vault/meteora.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_vault_meteora`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_vault_meteora"; +const LEGACY_CRATE: &str = "kb_executor_vault_meteora"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/vesting.rs b/kb-lib/src/executor/vesting.rs index c45954d..2402fad 100644 --- a/kb-lib/src/executor/vesting.rs +++ b/kb-lib/src/executor/vesting.rs @@ -3,4 +3,4 @@ //! `vesting` executor family. -pub mod streamflow; +mod streamflow; diff --git a/kb-lib/src/executor/vesting/streamflow.rs b/kb-lib/src/executor/vesting/streamflow.rs index fd7e62f..e77a21b 100644 --- a/kb-lib/src/executor/vesting/streamflow.rs +++ b/kb-lib/src/executor/vesting/streamflow.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_vesting_streamflow`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_vesting_streamflow"; +const LEGACY_CRATE: &str = "kb_executor_vesting_streamflow"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/wallet.rs b/kb-lib/src/executor/wallet.rs index a2e9330..d8e0955 100644 --- a/kb-lib/src/executor/wallet.rs +++ b/kb-lib/src/executor/wallet.rs @@ -3,4 +3,4 @@ //! `wallet` executor family. -pub mod jupiter_apepro_smart_wallet; +mod jupiter_apepro_smart_wallet; diff --git a/kb-lib/src/executor/wallet/jupiter_apepro_smart_wallet.rs b/kb-lib/src/executor/wallet/jupiter_apepro_smart_wallet.rs index f64a725..09ea8cb 100644 --- a/kb-lib/src/executor/wallet/jupiter_apepro_smart_wallet.rs +++ b/kb-lib/src/executor/wallet/jupiter_apepro_smart_wallet.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_wallet_jupiter_apepro_smart_wallet`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_wallet_jupiter_apepro_smart_wallet"; +const LEGACY_CRATE: &str = "kb_executor_wallet_jupiter_apepro_smart_wallet"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/executor/weighted.rs b/kb-lib/src/executor/weighted.rs index e061b49..4381539 100644 --- a/kb-lib/src/executor/weighted.rs +++ b/kb-lib/src/executor/weighted.rs @@ -3,4 +3,4 @@ //! `weighted` executor family. -pub mod swap_stabble; +mod swap_stabble; diff --git a/kb-lib/src/executor/weighted/swap_stabble.rs b/kb-lib/src/executor/weighted/swap_stabble.rs index 460e5a1..976560c 100644 --- a/kb-lib/src/executor/weighted/swap_stabble.rs +++ b/kb-lib/src/executor/weighted/swap_stabble.rs @@ -4,7 +4,7 @@ //! Migration boundary for legacy crate `kb_executor_weighted_swap_stabble`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_executor_weighted_swap_stabble"; +const LEGACY_CRATE: &str = "kb_executor_weighted_swap_stabble"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/lib.rs b/kb-lib/src/lib.rs index 6bf06c3..dd2c345 100644 --- a/kb-lib/src/lib.rs +++ b/kb-lib/src/lib.rs @@ -1,520 +1,783 @@ // file: kb-lib/src/lib.rs -// version: 12 +// version: 13 //! Consolidated decoder, executor, materializer and shared model library. #![warn(missing_docs)] #![deny(unreachable_pub)] #![forbid(unsafe_code)] -pub mod decoder; -pub mod executor; -pub mod materializer; -pub mod model; +mod decoder; +mod executor; +mod materializer; +mod model; -/// One parsed SPL ElGamal registry instruction. -pub(crate) use crate::decoder::ParsedRegistryInstruction; -/// Current stable Associated Token Account decoded event contract version. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_EVENT_VERSION; -/// Exact Associated Token Account instructions published by the official interface. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_INSTRUCTION_ENTRIES; -/// Maximum retained account-key text length for the Associated Token Account decoder. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNT_KEY_BYTES; -/// Maximum retained instruction account count for the Associated Token Account decoder. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_ACCOUNTS; -/// Maximum retained semantic diagnostic count for the Associated Token Account decoder. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_DIAGNOSTICS; -/// Maximum retained Associated Token Account instruction payload size. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_INSTRUCTION_BYTES; -/// Maximum retained transaction account-key count for the Associated Token Account decoder. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_MAX_TRANSACTION_KEYS; -/// Stable protocol and surface code for the Associated Token Account program. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_SURFACE_CODE; -/// Canonical tracing target for the Associated Token Account decoder. -pub(crate) use crate::decoder::SPL_ASSOCIATED_TOKEN_ACCOUNT_TRACING_TARGET; -/// Current stable SPL ElGamal registry event contract version. -pub(crate) use crate::decoder::SPL_ELGAMAL_REGISTRY_EVENT_VERSION; -/// Maximum retained SPL ElGamal registry instruction payload size. -pub(crate) use crate::decoder::SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; -/// Stable SPL ElGamal registry surface code. -pub(crate) use crate::decoder::SPL_ELGAMAL_REGISTRY_SURFACE_CODE; -/// Canonical tracing target for the SPL ElGamal registry decoder. -pub(crate) use crate::decoder::SPL_ELGAMAL_REGISTRY_TRACING_TARGET; -/// Maximum payload prefix retained for bounded Memo diagnostics. -pub(crate) use crate::decoder::SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; -/// Current stable Memo decoded event contract version. -pub(crate) use crate::decoder::SPL_MEMO_EVENT_VERSION; -/// Maximum decoded instruction data retained as a complete Memo payload. -pub(crate) use crate::decoder::SPL_MEMO_MAX_PAYLOAD_BYTES; -/// Stable protocol code shared by Memo generations. -pub(crate) use crate::decoder::SPL_MEMO_PROTOCOL_CODE; -/// Canonical tracing target for the SPL Memo decoder. -pub(crate) use crate::decoder::SPL_MEMO_TRACING_TARGET; -/// Stable Memo v1 surface code. -pub(crate) use crate::decoder::SPL_MEMO_V1_SURFACE_CODE; -/// Stable Memo v3 surface code. -pub(crate) use crate::decoder::SPL_MEMO_V3_SURFACE_CODE; -/// Stable Memo v4 surface code. -pub(crate) use crate::decoder::SPL_MEMO_V4_SURFACE_CODE; -/// Maximum prefix retained in bounded Token-2022 diagnostics. -pub(crate) use crate::decoder::SPL_TOKEN_2022_DIAGNOSTIC_PREFIX_BYTES; -/// Current stable Token-2022 decoded event contract version. -pub(crate) use crate::decoder::SPL_TOKEN_2022_EVENT_VERSION; -/// Exact top-level instruction inventory published by the resolved Token-2022 interface. -pub(crate) use crate::decoder::SPL_TOKEN_2022_INSTRUCTION_ENTRIES; -/// Maximum total account metas consumed by one Token-2022 batch. -pub(crate) use crate::decoder::SPL_TOKEN_2022_MAX_BATCH_ACCOUNTS; -/// Maximum decoded sub-instructions in one Token-2022 batch. -pub(crate) use crate::decoder::SPL_TOKEN_2022_MAX_BATCH_INSTRUCTIONS; -/// Maximum retained Token-2022 instruction payload size. -pub(crate) use crate::decoder::SPL_TOKEN_2022_MAX_INSTRUCTION_BYTES; -/// Maximum retained UTF-8 string size for embedded Token Metadata instructions. -pub(crate) use crate::decoder::SPL_TOKEN_2022_MAX_METADATA_STRING_BYTES; -/// Stable Token-2022 surface code. -pub(crate) use crate::decoder::SPL_TOKEN_2022_SURFACE_CODE; -/// Canonical tracing target for the Token-2022 decoder. -pub(crate) use crate::decoder::SPL_TOKEN_2022_TRACING_TARGET; -/// Maximum prefix retained in bounded classic SPL Token diagnostics. -pub(crate) use crate::decoder::SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; -/// Current stable classic SPL Token decoded event contract version. -pub(crate) use crate::decoder::SPL_TOKEN_EVENT_VERSION; -/// One exact classic SPL Token instruction entry published by the official interface. -pub(crate) use crate::decoder::SPL_TOKEN_INSTRUCTION_ENTRIES; -/// Maximum total account metas consumed by one classic SPL Token batch. -pub(crate) use crate::decoder::SPL_TOKEN_MAX_BATCH_ACCOUNTS; -/// Maximum decoded sub-instructions in one classic SPL Token batch. -pub(crate) use crate::decoder::SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; -/// Maximum retained classic SPL Token instruction payload size. -pub(crate) use crate::decoder::SPL_TOKEN_MAX_INSTRUCTION_BYTES; -/// Stable protocol and surface code for the classic SPL Token program. -pub(crate) use crate::decoder::SPL_TOKEN_SURFACE_CODE; -/// Canonical tracing target for the classic SPL Token decoder. -pub(crate) use crate::decoder::SPL_TOKEN_TRACING_TARGET; -/// Stable Address Lookup Table surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE; -/// Stable deprecated immutable BPF Loader surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE; -/// Stable immutable BPF Loader v2 surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_BPF_LOADER_SURFACE_CODE; -/// Stable upgradeable BPF Loader surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE; -/// Stable Compute Budget surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE; -/// Stable Config Program surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_CONFIG_SURFACE_CODE; -/// Byte length of an Ed25519 public key. -pub(crate) use crate::decoder::solana::SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES; -/// Stable Ed25519 signature precompile surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_ED25519_SURFACE_CODE; -/// Stable Feature Gate surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_FEATURE_SURFACE_CODE; -/// Stable Loader v4 surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_LOADER_V4_SURFACE_CODE; -/// Maximum retained native instruction payload accepted by the first decoder phase. -pub(crate) use crate::decoder::solana::SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES; -/// Current native event payload contract version. -pub(crate) use crate::decoder::solana::SOLANA_CORE_NATIVE_EVENT_VERSION; -/// Stable Native Loader surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE; -/// Maximum number of component bytes retained as a hexadecimal event prefix. -pub(crate) use crate::decoder::solana::SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES; -/// Stable protocol code shared by native Solana events. -pub(crate) use crate::decoder::solana::SOLANA_CORE_PROTOCOL_CODE; -/// Byte length of a secp256k1 Ethereum address. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; -/// Stable secp256k1 signature precompile surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SECP256K1_SURFACE_CODE; -/// Runtime maximum number of secp256r1 signatures in one precompile instruction. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SECP256R1_MAX_SIGNATURES; -/// Byte length of a compressed secp256r1 public key. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES; -/// Stable secp256r1 signature precompile surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SECP256R1_SURFACE_CODE; -/// Byte length shared by compact Ed25519, secp256k1 and secp256r1 signatures. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SIGNATURE_BYTES; -/// Stable Slashing Program decoder surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SLASHING_SURFACE_CODE; -/// Stable Stake Program surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_STAKE_SURFACE_CODE; -/// Stable System Program surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_SYSTEM_SURFACE_CODE; +/// Approve Collection Authority discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR; +/// Approve Use Authority discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR; +/// Bubblegum Set Collection Size discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR; +/// Burn discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_BURN_DISCRIMINATOR; +/// Historical Burn Edition NFT discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_BURN_EDITION_NFT_DISCRIMINATOR; +/// Historical Burn NFT discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_BURN_NFT_DISCRIMINATOR; +/// Close Accounts discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CLOSE_ACCOUNTS_DISCRIMINATOR; +/// Close Escrow Account discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR; +/// Collect discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_COLLECT_DISCRIMINATOR; +/// Convert Master Edition V1 to V2 discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR; +/// Modern Create discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CREATE_DISCRIMINATOR; +/// Create Escrow Account discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CREATE_ESCROW_ACCOUNT_DISCRIMINATOR; +/// Historical Create Master Edition discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CREATE_MASTER_EDITION_DISCRIMINATOR; +/// Create Master Edition V3 discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CREATE_MASTER_EDITION_V3_DISCRIMINATOR; +/// Historical Create Metadata Account discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_DISCRIMINATOR; +/// Historical Create Metadata Account V2 discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +/// Create Metadata Account V3 discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR; +/// Delegate discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_DELEGATE_DISCRIMINATOR; +/// Deprecated Create Master Edition discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR; +/// Deprecated Create Reservation List discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR; +/// Deprecated printing-token mint-new-edition discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR; +/// Deprecated Mint Printing Tokens discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR; +/// Deprecated Mint Printing Tokens Via Token discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR; +/// Deprecated Set Reservation List discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR; +/// Number of bytes retained in malformed-wire diagnostics. +pub(crate) use self::decoder::DC_METADATA_MTM_DIAGNOSTIC_PREFIX_BYTES; +/// Stable event payload contract version. +pub(crate) use self::decoder::DC_METADATA_MTM_EVENT_VERSION; +/// Freeze Delegated Account discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR; +/// Current pre-release instruction inventory. +pub(crate) use self::decoder::DC_METADATA_MTM_INSTRUCTION_ENTRIES; +/// Lock discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_LOCK_DISCRIMINATOR; +/// Maximum encoded base64 instruction payload size. +pub(crate) use self::decoder::DC_METADATA_MTM_MAX_BASE64_BYTES; +/// Maximum number of instruction accounts accepted by this decoder. +pub(crate) use self::decoder::DC_METADATA_MTM_MAX_INSTRUCTION_ACCOUNTS; +/// Tracing target for this decoder. +/// Maximum retained instruction payload size. +pub(crate) use self::decoder::DC_METADATA_MTM_MAX_INSTRUCTION_BYTES; +/// Migrate discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_MIGRATE_DISCRIMINATOR; +/// Modern Mint discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_MINT_DISCRIMINATOR; +/// Mint New Edition From Master Edition Via Token discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR; +/// Mint New Edition From Master Edition Via Vault Proxy discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR; +/// Modern Print discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_PRINT_DISCRIMINATOR; +/// Puff Metadata discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_PUFF_METADATA_DISCRIMINATOR; +/// Remove Creator Verification discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR; +/// Resize discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_RESIZE_DISCRIMINATOR; +/// Revoke Collection Authority discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR; +/// Revoke discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_REVOKE_DISCRIMINATOR; +/// Revoke Use Authority discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_REVOKE_USE_AUTHORITY_DISCRIMINATOR; +/// Set And Verify Collection discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_SET_AND_VERIFY_COLLECTION_DISCRIMINATOR; +/// Set And Verify Sized Collection Item discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +/// Set Collection Size discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_SET_COLLECTION_SIZE_DISCRIMINATOR; +/// Set Token Standard discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_SET_TOKEN_STANDARD_DISCRIMINATOR; +/// Sign Metadata discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_SIGN_METADATA_DISCRIMINATOR; +/// Stable decoder surface code. +pub(crate) use self::decoder::DC_METADATA_MTM_SURFACE_CODE; +/// Thaw Delegated Account discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_THAW_DELEGATED_ACCOUNT_DISCRIMINATOR; /// Canonical tracing target for this crate. -pub(crate) use crate::decoder::solana::SOLANA_CORE_TRACING_TARGET; +pub(crate) use self::decoder::DC_METADATA_MTM_TRACING_TARGET; +/// Transfer discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_TRANSFER_DISCRIMINATOR; +/// Transfer Out Of Escrow discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR; +/// Unlock discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UNLOCK_DISCRIMINATOR; +/// Unverify Collection discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UNVERIFY_COLLECTION_DISCRIMINATOR; +/// Modern Unverify discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UNVERIFY_DISCRIMINATOR; +/// Unverify Sized Collection Item discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; +/// Modern Update discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UPDATE_DISCRIMINATOR; +/// Historical Update Metadata Account discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_DISCRIMINATOR; +/// Update Metadata Account V2 discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR; +/// Update Primary Sale Happened Via Token discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR; +/// Modern Use discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_USE_DISCRIMINATOR; +/// Utilize discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_UTILIZE_DISCRIMINATOR; +/// Verify Collection discriminator. +pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR; +/// Modern Verify 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; +/// 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. +pub(crate) use self::decoder::DC_SOLANA_CORE_BPF_LOADER_DEPRECATED_SURFACE_CODE; +/// Stable immutable BPF Loader v2 surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_BPF_LOADER_SURFACE_CODE; +/// Stable upgradeable BPF Loader surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_BPF_LOADER_UPGRADEABLE_SURFACE_CODE; +/// Stable Compute Budget surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_COMPUTE_BUDGET_SURFACE_CODE; +/// Stable Config Program surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_CONFIG_SURFACE_CODE; +/// Byte length of an Ed25519 public key. +pub(crate) use self::decoder::DC_SOLANA_CORE_ED25519_PUBLIC_KEY_BYTES; +/// Stable Ed25519 signature precompile surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_ED25519_SURFACE_CODE; +/// Stable Feature Gate surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_FEATURE_SURFACE_CODE; +/// Stable Loader v4 surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_LOADER_V4_SURFACE_CODE; +/// Maximum retained native instruction payload accepted by the first decoder phase. +pub(crate) use self::decoder::DC_SOLANA_CORE_MAX_NATIVE_INSTRUCTION_PAYLOAD_BYTES; +/// Current native event payload contract version. +pub(crate) use self::decoder::DC_SOLANA_CORE_NATIVE_EVENT_VERSION; +/// Stable Native Loader surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_NATIVE_LOADER_SURFACE_CODE; +/// Maximum number of component bytes retained as a hexadecimal event prefix. +pub(crate) use self::decoder::DC_SOLANA_CORE_PRECOMPILE_COMPONENT_PREFIX_BYTES; +/// Stable protocol code shared by native Solana events. +pub(crate) use self::decoder::DC_SOLANA_CORE_PROTOCOL_CODE; +/// Byte length of a secp256k1 Ethereum address. +pub(crate) use self::decoder::DC_SOLANA_CORE_SECP256K1_ETHEREUM_ADDRESS_BYTES; +/// Stable secp256k1 signature precompile surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_SECP256K1_SURFACE_CODE; +/// Runtime maximum number of secp256r1 signatures in one precompile instruction. +pub(crate) use self::decoder::DC_SOLANA_CORE_SECP256R1_MAX_SIGNATURES; +/// Byte length of a compressed secp256r1 public key. +pub(crate) use self::decoder::DC_SOLANA_CORE_SECP256R1_PUBLIC_KEY_BYTES; +/// Stable secp256r1 signature precompile surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_SECP256R1_SURFACE_CODE; +/// Byte length shared by compact Ed25519, secp256k1 and secp256r1 signatures. +pub(crate) use self::decoder::DC_SOLANA_CORE_SIGNATURE_BYTES; +/// Stable Slashing Program decoder surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_SLASHING_SURFACE_CODE; +/// Stable Stake Program surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_STAKE_SURFACE_CODE; +/// Stable System Program surface code. +pub(crate) use self::decoder::DC_SOLANA_CORE_SYSTEM_SURFACE_CODE; +/// Canonical tracing target for this crate. +pub(crate) use self::decoder::DC_SOLANA_CORE_TRACING_TARGET; /// Byte length of one secp256k1 offsets entry. -pub(crate) use crate::decoder::solana::SOLANA_CORE_U8_OFFSETS_BYTES; +pub(crate) use self::decoder::DC_SOLANA_CORE_U8_OFFSETS_BYTES; /// Byte length of one Ed25519 or secp256r1 offsets entry. -pub(crate) use crate::decoder::solana::SOLANA_CORE_U16_OFFSETS_BYTES; +pub(crate) use self::decoder::DC_SOLANA_CORE_U16_OFFSETS_BYTES; /// Stable Vote Program surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_VOTE_SURFACE_CODE; +pub(crate) use self::decoder::DC_SOLANA_CORE_VOTE_SURFACE_CODE; /// Stable native ZK ElGamal Proof surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE; +pub(crate) use self::decoder::DC_SOLANA_CORE_ZK_ELGAMAL_PROOF_SURFACE_CODE; /// Stable historical ZK Token Proof surface code. -pub(crate) use crate::decoder::solana::SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE; +pub(crate) use self::decoder::DC_SOLANA_CORE_ZK_TOKEN_PROOF_SURFACE_CODE; +/// Current stable Associated Token Account decoded event contract version. +pub(crate) use self::decoder::DC_SPL_ATA_EVENT_VERSION; +/// Exact Associated Token Account instructions published by the official interface. +pub(crate) use self::decoder::DC_SPL_ATA_INSTRUCTION_ENTRIES; +/// Maximum retained account-key text length for the Associated Token Account decoder. +pub(crate) use self::decoder::DC_SPL_ATA_MAX_ACCOUNT_KEY_BYTES; +/// Maximum retained instruction account count for the Associated Token Account decoder. +pub(crate) use self::decoder::DC_SPL_ATA_MAX_ACCOUNTS; +/// Maximum retained semantic diagnostic count for the Associated Token Account decoder. +pub(crate) use self::decoder::DC_SPL_ATA_MAX_DIAGNOSTICS; +/// Maximum retained Associated Token Account instruction payload size. +pub(crate) use self::decoder::DC_SPL_ATA_MAX_INSTRUCTION_BYTES; +/// Maximum retained transaction account-key count for the Associated Token Account decoder. +pub(crate) use self::decoder::DC_SPL_ATA_MAX_TRANSACTION_KEYS; +/// Stable protocol and surface code for the Associated Token Account program. +pub(crate) use self::decoder::DC_SPL_ATA_SURFACE_CODE; +/// Canonical tracing target for the Associated Token Account decoder. +pub(crate) use self::decoder::DC_SPL_ATA_TRACING_TARGET; +/// Current stable SPL ElGamal registry event contract version. +pub(crate) use self::decoder::DC_SPL_ELGAMAL_REGISTRY_EVENT_VERSION; +/// Maximum retained SPL ElGamal registry instruction payload size. +pub(crate) use self::decoder::DC_SPL_ELGAMAL_REGISTRY_MAX_INSTRUCTION_BYTES; +/// Stable SPL ElGamal registry surface code. +pub(crate) use self::decoder::DC_SPL_ELGAMAL_REGISTRY_SURFACE_CODE; +/// Canonical tracing target for the SPL ElGamal registry decoder. +pub(crate) use self::decoder::DC_SPL_ELGAMAL_REGISTRY_TRACING_TARGET; +/// Maximum payload prefix retained for bounded Memo diagnostics. +pub(crate) use self::decoder::DC_SPL_MEMO_DIAGNOSTIC_PREFIX_BYTES; +/// Current stable Memo decoded event contract version. +pub(crate) use self::decoder::DC_SPL_MEMO_EVENT_VERSION; +/// Maximum decoded instruction data retained as a complete Memo payload. +pub(crate) use self::decoder::DC_SPL_MEMO_MAX_PAYLOAD_BYTES; +/// Stable protocol code shared by Memo generations. +pub(crate) use self::decoder::DC_SPL_MEMO_PROTOCOL_CODE; +/// Canonical tracing target for the SPL Memo decoder. +pub(crate) use self::decoder::DC_SPL_MEMO_TRACING_TARGET; +/// Stable Memo v1 surface code. +pub(crate) use self::decoder::DC_SPL_MEMO_V1_SURFACE_CODE; +/// Stable Memo v3 surface code. +pub(crate) use self::decoder::DC_SPL_MEMO_V3_SURFACE_CODE; +/// Stable Memo v4 surface code. +pub(crate) use self::decoder::DC_SPL_MEMO_V4_SURFACE_CODE; +/// Maximum prefix retained in bounded classic SPL Token diagnostics. +pub(crate) use self::decoder::DC_SPL_TOKEN_DIAGNOSTIC_PREFIX_BYTES; +/// Current stable classic SPL Token decoded event contract version. +pub(crate) use self::decoder::DC_SPL_TOKEN_EVENT_VERSION; +/// One exact classic SPL Token instruction entry published by the official interface. +pub(crate) use self::decoder::DC_SPL_TOKEN_INSTRUCTION_ENTRIES; +/// Maximum total account metas consumed by one classic SPL Token batch. +pub(crate) use self::decoder::DC_SPL_TOKEN_MAX_BATCH_ACCOUNTS; +/// Maximum decoded sub-instructions in one classic SPL Token batch. +pub(crate) use self::decoder::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS; +/// Maximum retained classic SPL Token instruction payload size. +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; +/// Canonical tracing target for the classic SPL Token decoder. +pub(crate) use self::decoder::DC_SPL_TOKEN_TRACING_TARGET; +/// Maximum prefix retained in bounded Token-2022 diagnostics. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_DIAGNOSTIC_PREFIX_BYTES; +/// Current stable Token-2022 decoded event contract version. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_EVENT_VERSION; +/// Exact top-level instruction inventory published by the resolved Token-2022 interface. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_INSTRUCTION_ENTRIES; +/// Maximum total account metas consumed by one Token-2022 batch. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_MAX_BATCH_ACCOUNTS; +/// Maximum decoded sub-instructions in one Token-2022 batch. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_MAX_BATCH_INSTRUCTIONS; +/// Maximum retained Token-2022 instruction payload size. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_MAX_INSTRUCTION_BYTES; +/// Maximum retained UTF-8 string size for embedded Token Metadata instructions. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_MAX_METADATA_STRING_BYTES; +/// Stable Token-2022 surface code. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_SURFACE_CODE; +/// Canonical tracing target for the Token-2022 decoder. +pub(crate) use self::decoder::DC_SPL_TOKEN2022_TRACING_TARGET; /// Expected role and privileges for one positional instruction account. -pub(crate) use crate::decoder::solana::SolanaCoreAccountRole; +pub(crate) use self::decoder::DcSolanaCoreAccountRole; /// One resolved outer instruction payload and its provenance relative to the target instruction. -pub(crate) use crate::decoder::solana::SolanaCoreResolvedInstructionPayload; +pub(crate) use self::decoder::DcSolanaCoreResolvedInstructionPayload; +/// One parsed SPL ElGamal registry instruction. +pub(crate) use self::decoder::DcSplElGamalRegistryParsedRegistryInstruction; +/// Crate-root access to `decode` from `instruction`. +pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_decode; +/// Crate-root access to `entry_for_discriminator` from `instruction`. +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; /// Returns declared Address Lookup Table instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_address_lookup_table_coverage; +pub(crate) use self::decoder::decoder_solana_core_address_lookup_table_coverage; /// Decodes one Address Lookup Table instruction. -pub(crate) use crate::decoder::solana::solana_core_address_lookup_table_decode; +pub(crate) use self::decoder::decoder_solana_core_address_lookup_table_decode; /// Recognizes one Address Lookup Table instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_address_lookup_table_recognize; +pub(crate) use self::decoder::decoder_solana_core_address_lookup_table_recognize; /// Returns a hexadecimal prefix no longer than the available byte slice. -pub(crate) use crate::decoder::solana::solana_core_bounded_hexadecimal_prefix; +pub(crate) use self::decoder::decoder_solana_core_bounded_hexadecimal_prefix; /// Extracts one exact bounded byte slice with checked arithmetic. -pub(crate) use crate::decoder::solana::solana_core_bounded_slice; +pub(crate) use self::decoder::decoder_solana_core_bounded_slice; /// Returns declared Compute Budget instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_compute_budget_coverage; +pub(crate) use self::decoder::decoder_solana_core_compute_budget_coverage; /// Decodes one Compute Budget instruction. -pub(crate) use crate::decoder::solana::solana_core_compute_budget_decode; +pub(crate) use self::decoder::decoder_solana_core_compute_budget_decode; /// Recognizes one Compute Budget instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_compute_budget_recognize; +pub(crate) use self::decoder::decoder_solana_core_compute_budget_recognize; /// Returns declared Config Program instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_config_coverage; +pub(crate) use self::decoder::decoder_solana_core_config_coverage; /// Decodes one generic Config Program store instruction. -pub(crate) use crate::decoder::solana::solana_core_config_decode; +pub(crate) use self::decoder::decoder_solana_core_config_decode; /// Recognizes one generic Config Program store instruction. -pub(crate) use crate::decoder::solana::solana_core_config_recognize; +pub(crate) use self::decoder::decoder_solana_core_config_recognize; /// Decodes one retained base64 instruction payload with an explicit byte limit. -pub(crate) use crate::decoder::solana::solana_core_decode_instruction_data; +pub(crate) use self::decoder::decoder_solana_core_decode_instruction_data; /// Returns the decoded target payload length when retained and valid. -pub(crate) use crate::decoder::solana::solana_core_decoded_payload_length; +pub(crate) use self::decoder::decoder_solana_core_decoded_payload_length; /// Returns the SHA-256 of the decoded target instruction data when available. -pub(crate) use crate::decoder::solana::solana_core_decoded_payload_sha256; +pub(crate) use self::decoder::decoder_solana_core_decoded_payload_sha256; /// Builds one exact decoded native observation. -pub(crate) use crate::decoder::solana::solana_core_decoded_result; +pub(crate) use self::decoder::decoder_solana_core_decoded_result; /// Builds one failed native decode result. -pub(crate) use crate::decoder::solana::solana_core_failed_result; +pub(crate) use self::decoder::decoder_solana_core_failed_result; /// Returns declared Feature Gate instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_feature_coverage; +pub(crate) use self::decoder::decoder_solana_core_feature_coverage; /// Decodes one Feature Gate instruction. -pub(crate) use crate::decoder::solana::solana_core_feature_decode; +pub(crate) use self::decoder::decoder_solana_core_feature_decode; /// Recognizes one Feature Gate instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_feature_recognize; +pub(crate) use self::decoder::decoder_solana_core_feature_recognize; /// Returns the lowercase SHA-256 of one bounded byte slice. -pub(crate) use crate::decoder::solana::solana_core_hash_bytes; +pub(crate) use self::decoder::decoder_solana_core_hash_bytes; /// Returns a normalized lowercase hexadecimal prefix. -pub(crate) use crate::decoder::solana::solana_core_hexadecimal_prefix; +pub(crate) use self::decoder::decoder_solana_core_hexadecimal_prefix; /// Returns declared loader instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_loaders_coverage; +pub(crate) use self::decoder::decoder_solana_core_loaders_coverage; /// Decodes one loader instruction. -pub(crate) use crate::decoder::solana::solana_core_loaders_decode; +pub(crate) use self::decoder::decoder_solana_core_loaders_decode; /// Recognizes one loader instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_loaders_recognize; +pub(crate) use self::decoder::decoder_solana_core_loaders_recognize; /// Returns a stable payload hash from core or computes it from retained JSON. -pub(crate) use crate::decoder::solana::solana_core_payload_hash; +pub(crate) use self::decoder::decoder_solana_core_payload_hash; /// Returns declared signature precompile coverage. -pub(crate) use crate::decoder::solana::solana_core_precompiles_coverage; +pub(crate) use self::decoder::decoder_solana_core_precompiles_coverage; /// Decodes one signature precompile instruction structurally without cryptographic recomputation. -pub(crate) use crate::decoder::solana::solana_core_precompiles_decode; +pub(crate) use self::decoder::decoder_solana_core_precompiles_decode; /// Recognizes one signature precompile instruction without resolving referenced data. -pub(crate) use crate::decoder::solana::solana_core_precompiles_recognize; +pub(crate) use self::decoder::decoder_solana_core_precompiles_recognize; /// Reads one little-endian `u32` from an exact byte range. -pub(crate) use crate::decoder::solana::solana_core_read_u32_le; +pub(crate) use self::decoder::decoder_solana_core_read_u32_le; /// Reads one little-endian `u64` from an exact byte range. -pub(crate) use crate::decoder::solana::solana_core_read_u64_le; +pub(crate) use self::decoder::decoder_solana_core_read_u64_le; /// Resolves positional instruction accounts and validates their core indexes. -pub(crate) use crate::decoder::solana::solana_core_resolve_accounts; +pub(crate) use self::decoder::decoder_solana_core_resolve_accounts; /// Resolves a secp256k1 instruction reference. The runtime format has no current-instruction /// sentinel: every `u8` value is an explicit outer instruction index. -pub(crate) use crate::decoder::solana::solana_core_resolve_u8_instruction_payload; +pub(crate) use self::decoder::decoder_solana_core_resolve_u8_instruction_payload; /// Resolves an Ed25519 or secp256r1 instruction reference using the official `u16::MAX` sentinel. -pub(crate) use crate::decoder::solana::solana_core_resolve_u16_instruction_payload; +pub(crate) use self::decoder::decoder_solana_core_resolve_u16_instruction_payload; /// Returns declared Slashing Program instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_slashing_coverage; +pub(crate) use self::decoder::decoder_solana_core_slashing_coverage; /// Decodes one Slashing Program instruction. -pub(crate) use crate::decoder::solana::solana_core_slashing_decode; +pub(crate) use self::decoder::decoder_solana_core_slashing_decode; /// Recognizes one Slashing Program instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_slashing_recognize; +pub(crate) use self::decoder::decoder_solana_core_slashing_recognize; /// Returns declared Stake Program instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_stake_coverage; +pub(crate) use self::decoder::decoder_solana_core_stake_coverage; /// Decodes one Stake Program instruction. -pub(crate) use crate::decoder::solana::solana_core_stake_decode; +pub(crate) use self::decoder::decoder_solana_core_stake_decode; /// Recognizes one Stake Program instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_stake_recognize; +pub(crate) use self::decoder::decoder_solana_core_stake_recognize; /// Returns declared System Program instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_system_coverage; +pub(crate) use self::decoder::decoder_solana_core_system_coverage; /// Decodes one System Program instruction. -pub(crate) use crate::decoder::solana::solana_core_system_decode; +pub(crate) use self::decoder::decoder_solana_core_system_decode; /// Recognizes one System Program instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_system_recognize; +pub(crate) use self::decoder::decoder_solana_core_system_recognize; /// Returns the numeric outer index of the target instruction. -pub(crate) use crate::decoder::solana::solana_core_target_outer_instruction_index; +pub(crate) use self::decoder::decoder_solana_core_target_outer_instruction_index; /// Builds one unsupported native decode result with a bounded diagnostic. -pub(crate) use crate::decoder::solana::solana_core_unsupported_result; +pub(crate) use self::decoder::decoder_solana_core_unsupported_result; /// Returns declared Vote Program instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_vote_coverage; +pub(crate) use self::decoder::decoder_solana_core_vote_coverage; /// Decodes one Vote Program instruction. -pub(crate) use crate::decoder::solana::solana_core_vote_decode; +pub(crate) use self::decoder::decoder_solana_core_vote_decode; /// Recognizes one Vote Program instruction without producing an event. -pub(crate) use crate::decoder::solana::solana_core_vote_recognize; +pub(crate) use self::decoder::decoder_solana_core_vote_recognize; /// Returns declared ZK ElGamal Proof instruction coverage. -pub(crate) use crate::decoder::solana::solana_core_zk_elgamal_coverage; +pub(crate) use self::decoder::decoder_solana_core_zk_elgamal_coverage; /// Decodes one native ZK ElGamal Proof instruction without recomputing the proof. -pub(crate) use crate::decoder::solana::solana_core_zk_elgamal_decode; +pub(crate) use self::decoder::decoder_solana_core_zk_elgamal_decode; /// Recognizes one native ZK ElGamal Proof instruction. -pub(crate) use crate::decoder::solana::solana_core_zk_elgamal_recognize; +pub(crate) use self::decoder::decoder_solana_core_zk_elgamal_recognize; /// Returns declared historical and current ZK Token Proof coverage. -pub(crate) use crate::decoder::solana::solana_core_zk_token_proof_coverage; +pub(crate) use self::decoder::decoder_solana_core_zk_token_proof_coverage; /// Decodes one historical ZK Token Proof layout without recomputing any proof. -pub(crate) use crate::decoder::solana::solana_core_zk_token_proof_decode; +pub(crate) use self::decoder::decoder_solana_core_zk_token_proof_decode; /// Recognizes one historical ZK Token Proof layout or the current no-op runtime fallback. -pub(crate) use crate::decoder::solana::solana_core_zk_token_proof_recognize; +pub(crate) use self::decoder::decoder_solana_core_zk_token_proof_recognize; /// Decodes one bounded Associated Token Account instruction. -pub(crate) use crate::decoder::spl_associated_token_account_decode; +pub(crate) use self::decoder::decoder_spl_associated_token_account_decode; /// Returns the exact entry matching an Associated Token Account wire. -pub(crate) use crate::decoder::spl_associated_token_account_entry; +pub(crate) use self::decoder::decoder_spl_associated_token_account_entry; /// Reads one bounded Associated Token Account payload. -pub(crate) use crate::decoder::spl_associated_token_account_payload; +pub(crate) use self::decoder::decoder_spl_associated_token_account_payload; /// Decodes one bounded SPL ElGamal registry instruction. -pub(crate) use crate::decoder::spl_elgamal_registry_decode; +pub(crate) use self::decoder::decoder_spl_elgamal_registry_decode; /// Decodes one bounded SPL ElGamal registry instruction payload. -pub(crate) use crate::decoder::spl_elgamal_registry_decode_payload; +pub(crate) use self::decoder::decoder_spl_elgamal_registry_decode_payload; /// Parses one exact SPL ElGamal registry instruction. -pub(crate) use crate::decoder::spl_elgamal_registry_parse; +pub(crate) use self::decoder::decoder_spl_elgamal_registry_parse; /// Decodes one bounded SPL Memo instruction. -pub(crate) use crate::decoder::spl_memo_decode; -/// Decodes one bounded Token-2022 instruction. -pub(crate) use crate::decoder::spl_token_2022_decode; -/// Returns the exact entry matching one Token-2022 tag. -pub(crate) use crate::decoder::spl_token_2022_entry_for_tag; -/// Returns the first byte of one retained Token-2022 payload. -pub(crate) use crate::decoder::spl_token_2022_payload_tag; +pub(crate) use self::decoder::decoder_spl_memo_decode; /// Decodes one bounded classic SPL Token instruction. -pub(crate) use crate::decoder::spl_token_decode; +pub(crate) use self::decoder::decoder_spl_token_decode; /// Returns the published entry matching one classic SPL Token tag. -pub(crate) use crate::decoder::spl_token_entry_for_tag; +pub(crate) use self::decoder::decoder_spl_token_entry_for_tag; /// Returns the first byte of one retained classic SPL Token payload. -pub(crate) use crate::decoder::spl_token_payload_tag; -/// Canonical tracing target for the native and SPL administration materializer. -pub(crate) use crate::materializer::admin::MATERIALIZER_ADMIN_TRACING_TARGET; +pub(crate) use self::decoder::decoder_spl_token_payload_tag; +/// Decodes one bounded Token-2022 instruction. +pub(crate) use self::decoder::decoder_spl_token2022_decode; +/// Returns the exact entry matching one Token-2022 tag. +pub(crate) use self::decoder::decoder_spl_token2022_entry_for_tag; +/// Returns the first byte of one retained Token-2022 payload. +pub(crate) use self::decoder::decoder_spl_token2022_payload_tag; /// Canonical processor name for the native and SPL administration materializer. -pub(crate) use crate::materializer::admin::PROCESSOR_NAME as MATERIALIZER_ADMIN_PROCESSOR_NAME; +pub(crate) use self::materializer::MT_ADMIN_PROCESSOR_NAME; +/// Canonical tracing target for the native and SPL administration materializer. +pub(crate) use self::materializer::MT_ADMIN_TRACING_TARGET; /// Canonical tracing target for the native compliance audit materializer. -pub(crate) use crate::materializer::compliance::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET; +pub(crate) use self::materializer::MT_COMPLIANCE_AUDIT_TRACING_TARGET; /// Canonical tracing target for the native lifecycle materializer. -pub(crate) use crate::materializer::lifecycle::MATERIALIZER_LIFECYCLE_TRACING_TARGET; +pub(crate) use self::materializer::MT_LIFECYCLE_TRACING_TARGET; +/// Stable processor name for SPL Token and ATA risk facts. +pub(crate) use self::materializer::MT_RISK_PROCESSOR_NAME; +/// Stable projection contract version for SPL Token and ATA risk facts. +pub(crate) use self::materializer::MT_RISK_PROJECTION_VERSION; +/// Canonical tracing target for SPL Token and ATA risk facts. +pub(crate) use self::materializer::MT_RISK_TRACING_TARGET; /// Canonical tracing target for the native stake and vote materializer. -pub(crate) use crate::materializer::staking::MATERIALIZER_STAKING_TRACING_TARGET; +pub(crate) use self::materializer::MT_STAKING_TRACING_TARGET; +/// Stable processor name for Token, ATA and Token-2022 account projections. +pub(crate) use self::materializer::MT_TOKEN_ACCOUNTS_PROCESSOR_NAME; +/// Stable projection contract version for Token, ATA and Token-2022 account projections. +pub(crate) use self::materializer::MT_TOKEN_ACCOUNTS_PROJECTION_VERSION; +/// Canonical tracing target for Token, ATA and Token-2022 account projections. +pub(crate) use self::materializer::MT_TOKEN_ACCOUNTS_TRACING_TARGET; +/// Maximum Memo payload accepted by transaction annotations. +pub(crate) use self::materializer::MT_TRANSACTION_ANNOTATIONS_MAX_MEMO_PAYLOAD_BYTES; +/// Stable processor name for transaction annotations. +pub(crate) use self::materializer::MT_TRANSACTION_ANNOTATIONS_PROCESSOR_NAME; +/// Stable projection contract version for transaction annotations. +pub(crate) use self::materializer::MT_TRANSACTION_ANNOTATIONS_PROJECTION_VERSION; +/// Canonical tracing target for transaction annotations. +pub(crate) use self::materializer::MT_TRANSACTION_ANNOTATIONS_TRACING_TARGET; -/// Exact byte length of one SPL ElGamal registry account. -pub use crate::decoder::ELGAMAL_REGISTRY_ACCOUNT_LEN; -/// Parsed SPL ElGamal public-key registry account. -pub use crate::decoder::ElGamalRegistryState; -/// Exact decoder for the Metaplex Token Metadata program. -pub use crate::decoder::MetadataMetaplexTokenMetadataDecoder; -/// Exact decoder for the SPL Associated Token Account program. -pub use crate::decoder::SplAssociatedTokenAccountDecoder; -/// Exact decoder for the SPL ElGamal registry program. -pub use crate::decoder::SplElgamalRegistryDecoder; -/// Exact decoder for the three registered SPL Memo generations. -pub use crate::decoder::SplMemoDecoder; -/// Exact decoder for the Token-2022 program. -pub use crate::decoder::SplToken2022Decoder; -/// Exact decoder for the classic SPL Token program. -pub use crate::decoder::SplTokenDecoder; -/// Parsed Token-2022 Mint, Account, or Multisig state. -pub use crate::decoder::Token2022State; -/// Exact Token-2022 base account state kind. -pub use crate::decoder::Token2022StateKind; -/// One exact Token-2022 TLV entry. -pub use crate::decoder::Token2022TlvEntry; /// Current contextual core instruction input contract version. -pub use crate::decoder::api::contracts::CORE_INSTRUCTION_INPUT_CONTRACT_VERSION; +pub use self::decoder::DC_API_CORE_INSTRUCTION_INPUT_CONTRACT_VERSION; +/// Exhaustive published Metaplex account-key inventory. +pub use self::decoder::DC_METADATA_MTM_METADATA_ACCOUNT_LAYOUT_AUDIT; +/// Exact byte length of one SPL ElGamal registry account. +pub use self::decoder::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN; /// Stable contextual decoded observation. -pub use crate::decoder::api::contracts::DecodedObservation; +pub use self::decoder::DcApiDecodedObservation; /// Machine-readable decoder coverage declaration. -pub use crate::decoder::api::contracts::DecoderCoverageDeclaration; +pub use self::decoder::DcApiDecoderCoverageDeclaration; /// Declared decoder coverage entry kind. -pub use crate::decoder::api::contracts::DecoderCoverageEntryKind; +pub use self::decoder::DcApiDecoderCoverageEntryKind; /// Structured decoder diagnostic. -pub use crate::decoder::api::contracts::DecoderDiagnostic; +pub use self::decoder::DcApiDecoderDiagnostic; /// Complete decoder execution result. -pub use crate::decoder::api::contracts::DecoderExecutionResult; +pub use self::decoder::DcApiDecoderExecutionResult; /// Stable decoder identity. -pub use crate::decoder::api::contracts::DecoderIdentity; +pub use self::decoder::DcApiDecoderIdentity; /// Decoder terminal result status. -pub use crate::decoder::api::contracts::DecoderOutcomeStatus; +pub use self::decoder::DcApiDecoderOutcomeStatus; /// Explicit decoding proof. -pub use crate::decoder::api::contracts::DecoderProof; +pub use self::decoder::DcApiDecoderProof; /// Decoding proof category. -pub use crate::decoder::api::contracts::DecoderProofKind; +pub use self::decoder::DcApiDecoderProofKind; /// Deterministic decoder recognition result. -pub use crate::decoder::api::contracts::DecoderRecognition; -/// One statically declared decoder surface. -pub use crate::decoder::api::contracts::DecoderSurface; -/// Contextual instruction decoder contract. -pub use crate::decoder::api::contracts::InstructionDecoder; -/// Computes the deterministic contextual input hash. -pub use crate::decoder::api::contracts::contextual_input_hash; -/// Returns true when a decoder declares the exact program id. -pub use crate::decoder::api::contracts::decoder_handles_program_id; -/// Computes a deterministic lowercase SHA-256 hash for one JSON value. -pub use crate::decoder::api::contracts::deterministic_json_hash; -/// Extracts the first eight payload bytes as hexadecimal when available. -pub use crate::decoder::api::contracts::discriminator_8_hex; +pub use self::decoder::DcApiDecoderRecognition; /// Exposes the decoder support level. -pub use crate::decoder::api::decoder::DecoderSupport; +pub use self::decoder::DcApiDecoderSupport; +/// One statically declared decoder surface. +pub use self::decoder::DcApiDecoderSurface; /// Initial decoder implementation placeholder for API-level tests. -pub use crate::decoder::api::decoder::InitialDecoder; +pub use self::decoder::DcApiInitialDecoder; +/// Contextual instruction decoder contract. +pub use self::decoder::DcApiInstructionDecoder; /// Exposes the common protocol decoder trait. -pub use crate::decoder::api::decoder::ProtocolDecoder; -/// Parses one exact SPL ElGamal registry account. -pub use crate::decoder::parse_elgamal_registry_state; -/// Parses one Token-2022 Mint, Account, or Multisig state. -pub use crate::decoder::parse_token_2022_state; +pub use self::decoder::DcApiProtocolDecoder; +/// Exact decoder for the Metaplex Token Metadata program. +/// Exact decoder for the Metaplex Token Metadata program. +pub use self::decoder::DcMetadataMetaplexTokenMetadataDecoder; +/// Canonical projection shared by Collection and Use Authority records. +pub use self::decoder::DcMetadataMtmAuthorityRecordAccountSnapshot; +/// Stable identity and policy of one canonical account snapshot. +pub use self::decoder::DcMetadataMtmCanonicalAccountIdentity; +/// Lifecycle represented by one canonical Metaplex account snapshot. +/// Lifecycle class of one canonical account layout. +pub use self::decoder::DcMetadataMtmCanonicalAccountLifecycle; +/// Provenance for one canonical Metaplex account snapshot. +/// Provenance retained for one canonical account observation. +pub use self::decoder::DcMetadataMtmCanonicalAccountProvenance; +/// Execution policy attached to one canonical Metaplex account layout. +/// Execution policy separated from historical materialization. +pub use self::decoder::DcMetadataMtmCanonicalExecutionPolicy; +/// Materialization policy attached to one canonical Metaplex account layout. +/// Materialization policy for active or historical state. +pub use self::decoder::DcMetadataMtmCanonicalMaterializationPolicy; +/// Canonical Metaplex account snapshot. +/// Canonical account envelope used by materializers and replay. +pub use self::decoder::DcMetadataMtmCanonicalMetadataAccountSnapshot; +/// Canonical state held by one Metaplex account snapshot. +/// Typed canonical Metaplex account state. +pub use self::decoder::DcMetadataMtmCanonicalMetadataAccountState; +/// Source of one canonical Metaplex account observation. +/// Origin of one canonical account observation. +pub use self::decoder::DcMetadataMtmCanonicalObservationSource; +/// Canonical projection shared by Metadata and Holder delegate records. +pub use self::decoder::DcMetadataMtmDelegateRecordAccountSnapshot; +/// Parsed Metaplex edition account kind. +/// Supported edition account layout. +pub use self::decoder::DcMetadataMtmEditionAccountKind; +/// Parsed Metaplex edition account snapshot. +/// Canonical bounded projection of one edition or master-edition account. +pub use self::decoder::DcMetadataMtmEditionAccountSnapshot; +/// Parsed Metaplex edition marker account kind. +/// Supported Edition Marker account layout. +pub use self::decoder::DcMetadataMtmEditionMarkerAccountKind; +/// Parsed Metaplex edition marker account snapshot. +/// Canonical bounded projection of one Edition Marker account. +pub use self::decoder::DcMetadataMtmEditionMarkerAccountSnapshot; +/// Bounded error returned while decoding a Metadata account. +pub use self::decoder::DcMetadataMtmMetadataAccountDecodeError; +/// One entry in the exhaustive published account-key audit. +pub use self::decoder::DcMetadataMtmMetadataAccountLayoutAuditEntry; +/// Parsed Metaplex MetadataV1 account snapshot. +/// Canonical bounded projection of one Metadata account. +pub use self::decoder::DcMetadataMtmMetadataAccountSnapshot; +/// One bounded historical reservation entry. +pub use self::decoder::DcMetadataMtmReservationEntrySnapshot; +/// Parsed Metaplex reservation-list account kind. +/// Historical Reservation List account generation. +pub use self::decoder::DcMetadataMtmReservationListAccountKind; +/// Parsed Metaplex reservation-list account snapshot. +/// Canonical decode-only projection of a historical Reservation List account. +pub use self::decoder::DcMetadataMtmReservationListAccountSnapshot; +/// Canonical projection of one Token Owned Escrow account. +pub use self::decoder::DcMetadataMtmTokenOwnedEscrowAccountSnapshot; +/// Authority form used by one Token Owned Escrow account. +pub use self::decoder::DcMetadataMtmTokenOwnedEscrowAuthorityKind; +/// Parsed Metaplex token-record account snapshot. +/// Canonical bounded projection of one programmable Token Record account. +pub use self::decoder::DcMetadataMtmTokenRecordAccountSnapshot; /// Runtime-native Solana decoder with maximal native instruction coverage. -pub use crate::decoder::solana::SolanaCoreDecoder; +pub use self::decoder::DcSolanaCoreDecoder; +/// Exact decoder for the SPL Associated Token Account program. +pub use self::decoder::DcSplAssociatedTokenAccountDecoder; +/// Parsed SPL ElGamal public-key registry account. +pub use self::decoder::DcSplElGamalRegistryState; +/// Exact decoder for the SPL ElGamal registry program. +pub use self::decoder::DcSplElgamalRegistryDecoder; +/// Exact decoder for the three registered SPL Memo generations. +pub use self::decoder::DcSplMemoDecoder; +/// Exact decoder for the Token-2022 program. +pub use self::decoder::DcSplToken2022Decoder; +/// Exact decoder for the classic SPL Token program. +pub use self::decoder::DcSplTokenDecoder; +/// Parsed Token-2022 Mint, Account, or Multisig state. +pub use self::decoder::DcToken2022State; +/// Exact Token-2022 base account state kind. +pub use self::decoder::DcToken2022StateKind; +/// One exact Token-2022 TLV entry. +pub use self::decoder::DcToken2022TlvEntry; +/// Computes the deterministic contextual input hash. +pub use self::decoder::decoder_api_decoder_api_contextual_input_hash; +/// Returns true when a decoder declares the exact program id. +pub use self::decoder::decoder_api_decoder_handles_program_id; +/// Computes a deterministic lowercase SHA-256 hash for one JSON value. +pub use self::decoder::decoder_api_deterministic_json_hash; +/// Extracts the first eight payload bytes as hexadecimal when available. +pub use self::decoder::decoder_api_discriminator_8_hex; +/// Decodes one Collection Authority Record account. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_collection_authority_record_account; +/// Decodes and validates one edition or master-edition account snapshot. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_edition_account; +/// Decodes and validates one Edition Marker account snapshot. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_edition_marker_account; +/// Decodes one Holder Delegate Record account. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_holder_delegate_record_account; +/// Decodes and validates one canonical Metadata account snapshot. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_metadata_account; +/// Decodes one Metadata Delegate Record account. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_metadata_delegate_record_account; +/// Decodes one historical Reservation List V1 or V2 account. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_reservation_list_account; +/// Decodes one Token Owned Escrow account. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_token_owned_escrow_account; +/// Decodes and validates one programmable Token Record account snapshot. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_token_record_account; +/// Decodes one Use Authority Record account. +pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_use_authority_record_account; +/// Parses one exact SPL ElGamal registry account. +pub use self::decoder::decoder_spl_elgamal_registry_parse_elgamal_registry_state; +/// Parses one Token-2022 Mint, Account, or Multisig state. +pub use self::decoder::decoder_spl_token2022_parse_token2022_state; /// Exposes the blockhash policy kind. -pub use crate::executor::api::execution::ExecutionBlockhashKind; +pub use self::executor::ExApiExecutionBlockhashKind; /// Exposes the blockhash policy. -pub use crate::executor::api::execution::ExecutionBlockhashPolicy; +pub use self::executor::ExApiExecutionBlockhashPolicy; /// Exposes the exact execution capability result. -pub use crate::executor::api::execution::ExecutionCapability; +pub use self::executor::ExApiExecutionCapability; /// Exposes supported Solana clusters. -pub use crate::executor::api::execution::ExecutionCluster; +pub use self::executor::ExApiExecutionCluster; /// Exposes cluster restrictions. -pub use crate::executor::api::execution::ExecutionClusterPolicy; +pub use self::executor::ExApiExecutionClusterPolicy; /// Exposes the result of waiting for transaction confirmation. -pub use crate::executor::api::execution::ExecutionConfirmationResult; +pub use self::executor::ExApiExecutionConfirmationResult; /// Exposes transaction confirmation states. -pub use crate::executor::api::execution::ExecutionConfirmationStatus; +pub use self::executor::ExApiExecutionConfirmationStatus; /// Exposes explicit execution cost ceilings. -pub use crate::executor::api::execution::ExecutionCostLimit; -/// Exposes the complete execution policy. -pub use crate::executor::api::execution::ExecutionPolicy; -/// Exposes the result of a transaction send adapter. -pub use crate::executor::api::execution::ExecutionSendResult; -/// Exposes the simulation policy. -pub use crate::executor::api::execution::ExecutionSimulationPolicy; -/// Exposes the simulation result contract. -pub use crate::executor::api::execution::ExecutionSimulationResult; -/// Exposes one planned instruction account. -pub use crate::executor::api::execution::PlannedAccount; -/// Exposes one encoded planned instruction. -pub use crate::executor::api::execution::PlannedInstruction; -/// Exposes post-execution replay diagnostics. -pub use crate::executor::api::execution::PostExecutionDiagnostic; -/// Exposes post-execution validation requirements. -pub use crate::executor::api::execution::PostExecutionValidationPolicy; -/// Exposes a typed execution plan. -pub use crate::executor::api::execution::PreparedExecutionPlan; -/// Exposes one required signer. -pub use crate::executor::api::execution::RequiredSigner; -/// Exposes the typed executor contract. -pub use crate::executor::api::execution::TypedInstructionExecutor; +pub use self::executor::ExApiExecutionCostLimit; /// Exposes the legacy common execution plan type. -pub use crate::executor::api::executor::ExecutionPlan; +pub use self::executor::ExApiExecutionPlan; +/// Exposes the complete execution policy. +pub use self::executor::ExApiExecutionPolicy; /// Exposes the legacy common execution request type. -pub use crate::executor::api::executor::ExecutionRequest; +pub use self::executor::ExApiExecutionRequest; +/// Exposes the result of a transaction send adapter. +pub use self::executor::ExApiExecutionSendResult; +/// Exposes the simulation policy. +pub use self::executor::ExApiExecutionSimulationPolicy; +/// Exposes the simulation result contract. +pub use self::executor::ExApiExecutionSimulationResult; /// Exposes the legacy common execution support enum. -pub use crate::executor::api::executor::ExecutionSupport; +pub use self::executor::ExApiExecutionSupport; /// Exposes the legacy common instruction executor trait. -pub use crate::executor::api::executor::InstructionExecutor; +pub use self::executor::ExApiInstructionExecutor; +/// Exposes one planned instruction account. +pub use self::executor::ExApiPlannedAccount; +/// Exposes one encoded planned instruction. +pub use self::executor::ExApiPlannedInstruction; +/// Exposes post-execution replay diagnostics. +pub use self::executor::ExApiPostExecutionDiagnostic; +/// Exposes post-execution validation requirements. +pub use self::executor::ExApiPostExecutionValidationPolicy; +/// Exposes a typed execution plan. +pub use self::executor::ExApiPreparedExecutionPlan; +/// Exposes one required signer. +pub use self::executor::ExApiRequiredSigner; +/// Exposes the typed executor contract. +pub use self::executor::ExApiTypedInstructionExecutor; /// Exposes the compact JSON payload serializer. -pub use crate::executor::api::executor::serialize_payload_json; +pub use self::executor::executor_api_serialize_payload_json; /// Exposes the pretty JSON payload serializer. -pub use crate::executor::api::executor::serialize_payload_json_pretty; +pub use self::executor::executor_api_serialize_payload_json_pretty; /// Stable native and SPL administration materializer. -pub use crate::materializer::admin::AdminMaterializer; -/// Materializes one exact SPL ElGamal registry account snapshot. -pub use crate::materializer::admin::materialize_elgamal_registry_state_snapshot; -/// Materializes exact Token-2022 administration account snapshots. -pub use crate::materializer::admin::materialize_token_2022_admin_state_snapshots; +pub use self::materializer::MtAdminMaterializer; /// Stable decoded observation materializer contract used by the common pipeline. -pub use crate::materializer::api::contracts::EventMaterializer; +pub use self::materializer::MtApiEventMaterializer; /// Explicit policy applied to successful and failed source transactions. -pub use crate::materializer::api::contracts::MaterializationTransactionPolicy; +pub use self::materializer::MtApiMaterializationTransactionPolicy; /// Stable processor-owned business output derived from one decoded observation. -pub use crate::materializer::api::contracts::MaterializedOutput; +pub use self::materializer::MtApiMaterializedOutput; /// Structured materializer diagnostic without generic error wrappers. -pub use crate::materializer::api::contracts::MaterializerDiagnostic; +pub use self::materializer::MtApiMaterializerDiagnostic; /// Complete explicit result produced by one materializer invocation. -pub use crate::materializer::api::contracts::MaterializerExecutionResult; +pub use self::materializer::MtApiMaterializerExecutionResult; /// Stable identity of one decoded event materializer. -pub use crate::materializer::api::contracts::MaterializerIdentity; +pub use self::materializer::MtApiMaterializerIdentity; /// Terminal materializer result status. -pub use crate::materializer::api::contracts::MaterializerOutcomeStatus; -/// Returns true when a materializer explicitly accepts one decoded family. -pub use crate::materializer::api::contracts::materializer_accepts_family; -/// Returns true when a materializer accepts one exact decoded observation. -pub use crate::materializer::api::contracts::materializer_accepts_observation; -/// Applies the mandatory source transaction policy before materialization. -pub use crate::materializer::api::contracts::validate_materialization_policy; -/// Rejects mutable business outputs derived from failed or uncommitted observations. -pub use crate::materializer::api::contracts::validate_materialized_output_policy; -/// Exposes the legacy common business materializer trait. -pub use crate::materializer::api::materializer::Materializer; +pub use self::materializer::MtApiMaterializerOutcomeStatus; /// Stable native compliance audit materializer. -pub use crate::materializer::compliance::ComplianceAuditMaterializer; +pub use self::materializer::MtComplianceAuditMaterializer; +/// Fee materializer for committed Token-2022 fee observations. +pub use self::materializer::MtFeesMaterializer; /// Stable native lifecycle materializer. -pub use crate::materializer::lifecycle::LifecycleMaterializer; +pub use self::materializer::MtLifecycleMaterializer; +/// Exposes the legacy common business materializer trait. +pub use self::materializer::MtMaterializer; +/// Token-2022 and Metaplex metadata snapshot materializer. +pub use self::materializer::MtMetadataMaterializer; +/// Stable SPL Token and ATA risk materializer. +pub use self::materializer::MtRiskMaterializer; /// Stable native stake and vote materializer. -pub use crate::materializer::staking::StakingMaterializer; +pub use self::materializer::MtStakingMaterializer; +/// Stable Token, ATA and Token-2022 account materializer. +pub use self::materializer::MtTokenAccountsMaterializer; +/// Stable committed Memo transaction annotation materializer. +pub use self::materializer::MtTransactionAnnotationMaterializer; +/// Materializes one canonical non-Metadata Metaplex account snapshot. +pub use self::materializer::materialize_metaplex_account_snapshot; +/// Materializes one canonical Metaplex Metadata account snapshot. +pub use self::materializer::materialize_metaplex_metadata_snapshot; +/// Materializes exact Token-2022 administration account snapshots. +pub use self::materializer::materialize_token2022_admin_state_snapshots; +/// Materializes authoritative Token-2022 fee extension snapshots. +pub use self::materializer::materialize_token2022_fee_state_snapshots; +/// Materializes Token-2022 embedded metadata and group snapshots. +pub use self::materializer::materialize_token2022_metadata_snapshot; +/// Materializes one bounded Token-2022 account state snapshot. +pub use self::materializer::materialize_token2022_state_snapshot; +/// Materializes one exact SPL ElGamal registry account snapshot. +pub use self::materializer::materializer_admin_materialize_elgamal_registry_state_snapshot; +/// Returns true when a materializer explicitly accepts one decoded family. +pub use self::materializer::materializer_api_accepts_family; +/// Returns true when a materializer accepts one exact decoded observation. +pub use self::materializer::materializer_api_accepts_observation; +/// Applies the mandatory source transaction policy before materialization. +pub use self::materializer::materializer_api_validate_materialization_policy; +/// Rejects mutable business outputs derived from failed or uncommitted observations. +pub use self::materializer::materializer_api_validate_materialized_output_policy; /// Current canonical transaction document version. -pub use crate::model::canonical_transaction::CANONICAL_TRANSACTION_FORMAT_VERSION; -/// Canonical address lookup table reference. -pub use crate::model::canonical_transaction::CanonicalAddressTableLookup; -/// Canonical compiled Solana instruction. -pub use crate::model::canonical_transaction::CanonicalCompiledInstruction; -/// Canonical group of inner instructions. -pub use crate::model::canonical_transaction::CanonicalInnerInstructionGroup; -/// Canonical runtime-loaded addresses. -pub use crate::model::canonical_transaction::CanonicalLoadedAddresses; -/// Canonical Solana message header. -pub use crate::model::canonical_transaction::CanonicalMessageHeader; -/// Canonical transaction return data. -pub use crate::model::canonical_transaction::CanonicalReturnData; -/// Canonical transaction reward. -pub use crate::model::canonical_transaction::CanonicalReward; -/// Canonical exact token balance. -pub use crate::model::canonical_transaction::CanonicalTokenBalance; -/// Source-independent canonical Solana transaction. -pub use crate::model::canonical_transaction::CanonicalTransaction; -/// Canonical Solana transaction message. -pub use crate::model::canonical_transaction::CanonicalTransactionMessage; -/// Canonical Solana transaction execution metadata. -pub use crate::model::canonical_transaction::CanonicalTransactionMetadata; -/// Canonical Solana transaction execution status. -pub use crate::model::canonical_transaction::CanonicalTransactionStatus; -/// Canonical Solana transaction version. -pub use crate::model::canonical_transaction::CanonicalTransactionVersion; -/// Protocol-level decoded event produced by a decoder. -pub use crate::model::decoded::DecodedProtocolEvent; -/// Confidence level for a decoded event. -pub use crate::model::decoded::DecoderConfidence; -/// Source from which a decoded event was derived. -pub use crate::model::decoded::EventSourceKind; -/// Business-level materialized event placeholder. -pub use crate::model::materialized::MaterializedEvent; -/// Materialized event family. -pub use crate::model::materialized::MaterializedEventFamily; -/// Canonical event code in `.` format. -pub use crate::model::nomenclature::EventCode; -/// High-level event family. -pub use crate::model::nomenclature::EventFamily; -/// Event name without surface prefix. -pub use crate::model::nomenclature::EventName; -/// Stable internal program code. -pub use crate::model::nomenclature::ProgramCode; -/// Protocol family code, for example `raydium` or `meteora`. -pub use crate::model::nomenclature::ProtocolCode; -/// Concrete protocol surface code, for example `raydium_amm_v4`. -pub use crate::model::nomenclature::SurfaceCode; -/// Generic program observation derived from a Solana instruction. -pub use crate::model::observation::ProgramObservation; +pub use self::model::MD_CANONICAL_TRANSACTION_FORMAT_VERSION; /// Source-neutral replay contracts. /// Version of the normalized core replay contract. -pub use crate::model::replay::CORE_REPLAY_INPUT_CONTRACT_VERSION; +pub use self::model::MD_CORE_REPLAY_INPUT_CONTRACT_VERSION; +/// Canonical address lookup table reference. +pub use self::model::MdCanonicalAddressTableLookup; +/// Canonical compiled Solana instruction. +pub use self::model::MdCanonicalCompiledInstruction; +/// Canonical group of inner instructions. +pub use self::model::MdCanonicalInnerInstructionGroup; +/// Canonical runtime-loaded addresses. +pub use self::model::MdCanonicalLoadedAddresses; +/// Canonical Solana message header. +pub use self::model::MdCanonicalMessageHeader; +/// Canonical transaction return data. +pub use self::model::MdCanonicalReturnData; +/// Canonical transaction reward. +pub use self::model::MdCanonicalReward; +/// Canonical exact token balance. +pub use self::model::MdCanonicalTokenBalance; +/// Source-independent canonical Solana transaction. +pub use self::model::MdCanonicalTransaction; +/// Canonical Solana transaction message. +pub use self::model::MdCanonicalTransactionMessage; +/// Canonical Solana transaction execution metadata. +pub use self::model::MdCanonicalTransactionMetadata; +/// Canonical Solana transaction execution status. +pub use self::model::MdCanonicalTransactionStatus; +/// Canonical Solana transaction version. +pub use self::model::MdCanonicalTransactionVersion; /// Decoder replay input containing one instruction plus extracted transaction context. -pub use crate::model::replay::CoreInstructionReplayInput; +pub use self::model::MdCoreInstructionReplayInput; +/// Protocol-level decoded event produced by a decoder. +pub use self::model::MdDecodedProtocolEvent; +/// Confidence level for a decoded event. +pub use self::model::MdDecoderConfidence; +/// Canonical event code in `.` format. +pub use self::model::MdEventCode; +/// High-level event family. +pub use self::model::MdEventFamily; +/// Event name without surface prefix. +pub use self::model::MdEventName; +/// Source from which a decoded event was derived. +pub use self::model::MdEventSourceKind; /// Stable top-level or inner instruction path. -pub use crate::model::solana::InstructionPath; +pub use self::model::MdInstructionPath; +/// Business-level materialized event placeholder. +pub use self::model::MdMaterializedEvent; +/// Materialized event family. +pub use self::model::MdMaterializedEventFamily; +/// Stable internal program code. +pub use self::model::MdProgramCode; /// Solana program id. -pub use crate::model::solana::ProgramId; +pub use self::model::MdProgramId; +/// Generic program observation derived from a Solana instruction. +pub use self::model::MdProgramObservation; +/// Protocol family code, for example `raydium` or `meteora`. +pub use self::model::MdProtocolCode; /// Solana public key. -pub use crate::model::solana::Pubkey; +pub use self::model::MdPubkey; /// Solana transaction signature. -pub use crate::model::solana::Signature; +pub use self::model::MdSignature; /// Solana slot. -pub use crate::model::solana::Slot; +pub use self::model::MdSlot; +/// Concrete protocol surface code, for example `raydium_amm_v4`. +pub use self::model::MdSurfaceCode; diff --git a/kb-lib/src/materializer.rs b/kb-lib/src/materializer.rs index e8a56b5..4785c2a 100644 --- a/kb-lib/src/materializer.rs +++ b/kb-lib/src/materializer.rs @@ -1,28 +1,116 @@ // file: kb-lib/src/materializer.rs -// version: 1 +// version: 2 //! Consolidated materializer modules. -pub mod admin; -pub mod api; -pub mod bridge; -pub mod compliance; -pub mod fees; -pub mod governance; -pub mod lending; -pub mod lifecycle; -pub mod liquidity; -pub mod metadata; -pub mod nft; -pub mod oracle; -pub mod orderbook; -pub mod perpetuals; -pub mod pool; -pub mod rewards; -pub mod risk; -pub mod routing; -pub mod staking; -pub mod token; -pub mod trades; -pub mod transaction; -pub mod vault; +mod admin; +mod api; +mod bridge; +mod compliance; +mod fees; +mod governance; +mod lending; +mod lifecycle; +mod liquidity; +mod metadata; +mod nft; +mod oracle; +mod orderbook; +mod perpetuals; +mod pool; +mod rewards; +mod risk; +mod routing; +mod staking; +mod token; +mod trades; +mod transaction; +mod vault; + +/// Canonical processor name for the native and SPL administration materializer. +pub(crate) use self::admin::MT_ADMIN_PROCESSOR_NAME; +/// Canonical tracing target for the native and SPL administration materializer. +pub(crate) use self::admin::MT_ADMIN_TRACING_TARGET; +/// Canonical tracing target for the native compliance audit materializer. +pub(crate) use self::compliance::MT_COMPLIANCE_AUDIT_TRACING_TARGET; +/// Canonical tracing target for the native lifecycle materializer. +pub(crate) use self::lifecycle::MT_LIFECYCLE_TRACING_TARGET; +/// Stable processor name for SPL Token and ATA risk facts. +pub(crate) use self::risk::MT_RISK_PROCESSOR_NAME; +/// Stable projection contract version for SPL Token and ATA risk facts. +pub(crate) use self::risk::MT_RISK_PROJECTION_VERSION; +/// Canonical tracing target for SPL Token and ATA risk facts. +pub(crate) use self::risk::MT_RISK_TRACING_TARGET; +/// Canonical tracing target for the native stake and vote materializer. +pub(crate) use self::staking::MT_STAKING_TRACING_TARGET; +/// Stable processor name for Token, ATA and Token-2022 account projections. +pub(crate) use self::token::MT_TOKEN_ACCOUNTS_PROCESSOR_NAME; +/// Stable projection contract version for Token, ATA and Token-2022 account projections. +pub(crate) use self::token::MT_TOKEN_ACCOUNTS_PROJECTION_VERSION; +/// Canonical tracing target for Token, ATA and Token-2022 account projections. +pub(crate) use self::token::MT_TOKEN_ACCOUNTS_TRACING_TARGET; +/// Maximum Memo payload accepted by transaction annotations. +pub(crate) use self::transaction::MT_TRANSACTION_ANNOTATIONS_MAX_MEMO_PAYLOAD_BYTES; +/// Stable processor name for transaction annotations. +pub(crate) use self::transaction::MT_TRANSACTION_ANNOTATIONS_PROCESSOR_NAME; +/// Stable projection contract version for transaction annotations. +pub(crate) use self::transaction::MT_TRANSACTION_ANNOTATIONS_PROJECTION_VERSION; +/// Canonical tracing target for transaction annotations. +pub(crate) use self::transaction::MT_TRANSACTION_ANNOTATIONS_TRACING_TARGET; + +/// Stable native and SPL administration materializer. +pub use self::admin::MtAdminMaterializer; +/// Materializes exact Token-2022 administration account snapshots. +pub use self::admin::materialize_token2022_admin_state_snapshots; +/// Materializes one exact SPL ElGamal registry account snapshot. +pub use self::admin::materializer_admin_materialize_elgamal_registry_state_snapshot; +/// Stable decoded observation materializer contract used by the common pipeline. +pub use self::api::MtApiEventMaterializer; +/// Explicit policy applied to successful and failed source transactions. +pub use self::api::MtApiMaterializationTransactionPolicy; +/// Stable processor-owned business output derived from one decoded observation. +pub use self::api::MtApiMaterializedOutput; +/// Structured materializer diagnostic without generic error wrappers. +pub use self::api::MtApiMaterializerDiagnostic; +/// Complete explicit result produced by one materializer invocation. +pub use self::api::MtApiMaterializerExecutionResult; +/// Stable identity of one decoded event materializer. +pub use self::api::MtApiMaterializerIdentity; +/// Terminal materializer result status. +pub use self::api::MtApiMaterializerOutcomeStatus; +/// Exposes the legacy common business materializer trait. +pub use self::api::MtMaterializer; +/// Returns true when a materializer explicitly accepts one decoded family. +pub use self::api::materializer_api_accepts_family; +/// Returns true when a materializer accepts one exact decoded observation. +pub use self::api::materializer_api_accepts_observation; +/// Applies the mandatory source transaction policy before materialization. +pub use self::api::materializer_api_validate_materialization_policy; +/// Rejects mutable business outputs derived from failed or uncommitted observations. +pub use self::api::materializer_api_validate_materialized_output_policy; +/// Stable native compliance audit materializer. +pub use self::compliance::MtComplianceAuditMaterializer; +/// Fee materializer for committed Token-2022 fee observations. +pub use self::fees::MtFeesMaterializer; +/// Materializes authoritative Token-2022 fee extension snapshots. +pub use self::fees::materialize_token2022_fee_state_snapshots; +/// Stable native lifecycle materializer. +pub use self::lifecycle::MtLifecycleMaterializer; +/// Token-2022 and Metaplex metadata snapshot materializer. +pub use self::metadata::MtMetadataMaterializer; +/// Materializes one canonical non-Metadata Metaplex account snapshot. +pub use self::metadata::materialize_metaplex_account_snapshot; +/// Materializes one canonical Metaplex Metadata account snapshot. +pub use self::metadata::materialize_metaplex_metadata_snapshot; +/// Materializes Token-2022 embedded metadata and group snapshots. +pub use self::metadata::materialize_token2022_metadata_snapshot; +/// Stable SPL Token and ATA risk materializer. +pub use self::risk::MtRiskMaterializer; +/// Stable native stake and vote materializer. +pub use self::staking::MtStakingMaterializer; +/// Stable Token, ATA and Token-2022 account materializer. +pub use self::token::MtTokenAccountsMaterializer; +/// Materializes one bounded Token-2022 account state snapshot. +pub use self::token::materialize_token2022_state_snapshot; +/// Stable committed Memo transaction annotation materializer. +pub use self::transaction::MtTransactionAnnotationMaterializer; diff --git a/kb-lib/src/materializer/admin.rs b/kb-lib/src/materializer/admin.rs index 5557275..6752f17 100644 --- a/kb-lib/src/materializer/admin.rs +++ b/kb-lib/src/materializer/admin.rs @@ -1,17 +1,19 @@ // file: kb-lib/src/materializer/admin.rs -// version: 2 +// version: 3 //! `admin` materializer family. mod constants; -pub mod core; +mod core; -pub(crate) use crate::materializer::admin::constants::PROCESSOR_NAME; -pub(crate) use crate::materializer::admin::constants::TRACING_TARGET as MATERIALIZER_ADMIN_TRACING_TARGET; +/// Canonical processor name for the native and SPL administration materializer. +pub(crate) use self::constants::MT_ADMIN_PROCESSOR_NAME; +/// Canonical tracing target for the native and SPL administration materializer. +pub(crate) use self::constants::MT_ADMIN_TRACING_TARGET; /// Stable native and SPL administration materializer. -pub use crate::materializer::admin::core::AdminMaterializer; -/// Materializes one exact SPL ElGamal registry account snapshot. -pub use crate::materializer::admin::core::materialize_elgamal_registry_state_snapshot; +pub use self::core::MtAdminMaterializer; /// Materializes exact Token-2022 administration account snapshots. -pub use crate::materializer::admin::core::materialize_token_2022_admin_state_snapshots; +pub use self::core::materialize_token2022_admin_state_snapshots; +/// Materializes one exact SPL ElGamal registry account snapshot. +pub use self::core::materializer_admin_materialize_elgamal_registry_state_snapshot; diff --git a/kb-lib/src/materializer/admin/constants.rs b/kb-lib/src/materializer/admin/constants.rs index b7441fb..c3afa35 100644 --- a/kb-lib/src/materializer/admin/constants.rs +++ b/kb-lib/src/materializer/admin/constants.rs @@ -4,7 +4,7 @@ //! Local constants for the native and SPL administration materializer. /// Canonical processor name for this component. -pub(crate) const PROCESSOR_NAME: &str = "solana_native_admin"; +pub(crate) const MT_ADMIN_PROCESSOR_NAME: &str = "solana_native_admin"; /// Canonical tracing target for this component. -pub(crate) const TRACING_TARGET: &str = "kb-lib.materializer.admin"; +pub(crate) const MT_ADMIN_TRACING_TARGET: &str = "kb-lib.materializer.admin"; diff --git a/kb-lib/src/materializer/admin/core.rs b/kb-lib/src/materializer/admin/core.rs index cb0f8da..87d5b32 100644 --- a/kb-lib/src/materializer/admin/core.rs +++ b/kb-lib/src/materializer/admin/core.rs @@ -3,8 +3,8 @@ //! Stable administrative projections derived from exact committed observations. -const ACCEPTED_FAMILIES: &[crate::EventFamily] = - &[crate::EventFamily::Admin, crate::EventFamily::TokenAccount]; +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = + &[crate::MdEventFamily::Admin, crate::MdEventFamily::TokenAccount]; const SYSTEM_SURFACE: &str = "solana_native_system"; const SYSTEM_ENTRIES: &[&str] = &["assign", "assign_with_seed"]; const CONFIG_SURFACE: &str = "solana_native_config"; @@ -14,7 +14,7 @@ const BPF_LOADER_UPGRADEABLE_ENTRIES: &[&str] = &["set_authority", "set_authorit const LOADER_V4_SURFACE: &str = "solana_native_loader_v4"; const LOADER_V4_ENTRIES: &[&str] = &["transfer_authority"]; const SPL_TOKEN_SURFACE: &str = "spl_token"; -const SPL_TOKEN_2022_SURFACE: &str = "spl_token_2022"; +const SPL_TOKEN2022_SURFACE: &str = "spl_token2022"; const SPL_ELGAMAL_REGISTRY_SURFACE: &str = "spl_elgamal_registry"; const SPL_ELGAMAL_REGISTRY_ENTRIES: &[&str] = &["create_registry", "update_registry"]; const SPL_TOKEN_AUTHORITY_ENTRIES: &[&str] = &[ @@ -24,7 +24,7 @@ const SPL_TOKEN_AUTHORITY_ENTRIES: &[&str] = &[ "update_interest_bearing_rate", ]; const SPL_TOKEN_MULTISIG_ENTRIES: &[&str] = &["initialize_multisig", "initialize_multisig2"]; -const SPL_TOKEN_2022_EXTENSION_ADMIN_ENTRIES: &[&str] = &[ +const SPL_TOKEN2022_EXTENSION_ADMIN_ENTRIES: &[&str] = &[ "initialize_transfer_hook", "update_transfer_hook_program_id", "initialize_metadata_pointer", @@ -57,7 +57,7 @@ impl ProjectionKind { Self::SplTokenAuthority => "spl_token_authority", Self::SplTokenMultisig => "spl_token_multisig", Self::SplElgamalRegistry => "spl_elgamal_registry", - Self::SplToken2022ExtensionAdmin => "spl_token_2022_extension_admin", + Self::SplToken2022ExtensionAdmin => "spl_token2022_extension_admin", }; } @@ -79,7 +79,7 @@ impl ProjectionKind { Self::SplTokenMultisig => format!("spl_token_multisig:{operation}:0"), Self::SplElgamalRegistry => format!("spl_elgamal_registry:{operation}:0"), Self::SplToken2022ExtensionAdmin => { - format!("spl_token_2022_extension_admin:{operation}:0") + format!("spl_token2022_extension_admin:{operation}:0") }, }; } @@ -87,9 +87,9 @@ impl ProjectionKind { /// Stable administrative materializer for supported native mutations. #[derive(Clone, Debug, Default)] -pub struct AdminMaterializer; +pub struct MtAdminMaterializer; -impl crate::Materializer for crate::AdminMaterializer { +impl crate::MtMaterializer for crate::MtAdminMaterializer { fn materializer_name(&self) -> &'static str { return "kb_materializer_admin"; } @@ -98,7 +98,7 @@ impl crate::Materializer for crate::AdminMaterializer { return env!("CARGO_PKG_VERSION"); } - fn accepts_event(&self, event: &crate::DecodedProtocolEvent) -> bool { + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { return ACCEPTED_FAMILIES.contains(&event.event_family) && program_matches_surface(event) && projection(event.surface_code.0.as_str(), event.event_name.0.as_str()).is_some(); @@ -106,28 +106,28 @@ impl crate::Materializer for crate::AdminMaterializer { fn materialize_event( &self, - event: &crate::DecodedProtocolEvent, - ) -> kb_core::Result> { - if !crate::Materializer::accepts_event(self, event) { + event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + if !crate::MtMaterializer::accepts_event(self, event) { return std::result::Result::Ok(std::vec::Vec::new()); } return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::EventMaterializer for crate::AdminMaterializer { - fn identity(&self) -> crate::MaterializerIdentity { - return crate::MaterializerIdentity { +impl crate::MtApiEventMaterializer for crate::MtAdminMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { name: "solana_native_admin".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn accepted_families(&self) -> &'static [crate::EventFamily] { + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { return ACCEPTED_FAMILIES; } - fn accepts_observation(&self, observation: &crate::DecodedObservation) -> bool { + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { return ACCEPTED_FAMILIES.contains(&observation.event.event_family) && program_matches_surface(&observation.event) && projection( @@ -139,15 +139,15 @@ impl crate::EventMaterializer for crate::AdminMaterializer { fn transaction_policy( &self, - _family: crate::EventFamily, - ) -> crate::MaterializationTransactionPolicy { - return crate::MaterializationTransactionPolicy::SuccessfulCommittedOnly; + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; } fn materialize( &self, - observation: &crate::DecodedObservation, - ) -> crate::MaterializerExecutionResult { + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { let projection = match projection( observation.event.surface_code.0.as_str(), observation.event.event_name.0.as_str(), @@ -155,25 +155,25 @@ impl crate::EventMaterializer for crate::AdminMaterializer { std::option::Option::Some(value) => value, std::option::Option::None => { tracing::debug!( - target: crate::MATERIALIZER_ADMIN_TRACING_TARGET, + target: crate::MT_ADMIN_TRACING_TARGET, action = "materialize_admin", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), accepted = false, "ignore observation outside supported native administrative projections" ); - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); }, }; if !ACCEPTED_FAMILIES.contains(&observation.event.event_family) { - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); } if !program_matches_surface(&observation.event) { - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); } if observation.transaction_failed || !observation.observation_committed { tracing::debug!( - target: crate::MATERIALIZER_ADMIN_TRACING_TARGET, + target: crate::MT_ADMIN_TRACING_TARGET, action = "materialize_admin", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -181,7 +181,7 @@ impl crate::EventMaterializer for crate::AdminMaterializer { transaction_failed = observation.transaction_failed, "refuse uncommitted native administrative observation" ); - return crate::MaterializerExecutionResult::refused( + return crate::MtApiMaterializerExecutionResult::refused( "failed_transaction_admin_refused", "failed or uncommitted native observations cannot create administrative mutation outputs", ); @@ -197,10 +197,10 @@ impl crate::EventMaterializer for crate::AdminMaterializer { .cloned() .unwrap_or_else(|| return observation.payload_json.clone()); let operation = observation.event.event_name.0.clone(); - let output = crate::MaterializedOutput { + let output = crate::MtApiMaterializedOutput { output_key: projection .output_key(observation.event.surface_code.0.as_str(), operation.as_str()), - family: crate::MaterializedEventFamily::Admin, + family: crate::MdMaterializedEventFamily::Admin, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "committed_instruction_admin_event", @@ -223,7 +223,7 @@ impl crate::EventMaterializer for crate::AdminMaterializer { }), }; tracing::debug!( - target: crate::MATERIALIZER_ADMIN_TRACING_TARGET, + target: crate::MT_ADMIN_TRACING_TARGET, action = "materialize_admin", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -231,8 +231,8 @@ impl crate::EventMaterializer for crate::AdminMaterializer { output_count = 1_usize, "materialize committed native administrative observation" ); - return crate::MaterializerExecutionResult { - status: crate::MaterializerOutcomeStatus::Inserted, + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, outputs: std::vec![output], diagnostics: std::vec::Vec::new(), }; @@ -258,18 +258,18 @@ fn projection(surface_code: &str, entry_code: &str) -> std::option::Option std::option::Option bool { +fn program_matches_surface(event: &crate::MdDecodedProtocolEvent) -> bool { if event.surface_code.0 == SPL_TOKEN_SURFACE { return event.program_id.0 == kb_program_ids::SPL_TOKEN_PROGRAM_ID; } - if event.surface_code.0 == SPL_TOKEN_2022_SURFACE { - return event.program_id.0 == kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID; + if event.surface_code.0 == SPL_TOKEN2022_SURFACE { + return event.program_id.0 == kb_program_ids::SPL_TOKEN2022_PROGRAM_ID; } if event.surface_code.0 == SPL_ELGAMAL_REGISTRY_SURFACE { - return event.program_id.0 == kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID; + return event.program_id.0 == kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID; } return true; } @@ -497,21 +497,21 @@ mod tests { transaction_failed: bool, accounts: serde_json::Value, parameters: serde_json::Value, - ) -> crate::DecodedObservation { - return crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { event_key: format!("{entry_code}:0"), - event: crate::DecodedProtocolEvent { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(42), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId("program-id".to_string()), - protocol_code: crate::ProtocolCode("solana_native".to_string()), - surface_code: crate::SurfaceCode(surface_code.to_string()), - event_code: crate::EventCode(format!("{surface_code}.{entry_code}")), - event_name: crate::EventName(entry_code.to_string()), - event_family: crate::EventFamily::Admin, - source_kind: crate::EventSourceKind::Instruction, - confidence: crate::DecoderConfidence::ManualExact, + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId("program-id".to_string()), + protocol_code: crate::MdProtocolCode("solana_native".to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")), + event_name: crate::MdEventName(entry_code.to_string()), + event_family: crate::MdEventFamily::Admin, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, }, payload_json: serde_json::json!({"accounts": accounts, "parameters": parameters}), transaction_failed, @@ -521,9 +521,9 @@ mod tests { std::option::Option::None }, observation_committed: !transaction_failed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec!["fixture".to_string()], }, }; @@ -535,7 +535,7 @@ mod tests { #[test] fn system_assign_creates_owner_projection() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; let observation = observation( super::SYSTEM_SURFACE, "assign", @@ -543,16 +543,16 @@ mod tests { serde_json::json!([account("assigned_account", "account111",)]), serde_json::json!({"owner": "owner111"}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); - assert_eq!(result.outputs[0].family, crate::MaterializedEventFamily::Admin); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs[0].family, crate::MdMaterializedEventFamily::Admin); assert_eq!(result.outputs[0].output_key, "system_account_ownership:assign:0"); assert_eq!(result.outputs[0].payload_json["projection"]["newOwner"], "owner111"); } #[test] fn seeded_assign_preserves_base_seed_and_owner() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; let observation = observation( super::SYSTEM_SURFACE, "assign_with_seed", @@ -563,7 +563,7 @@ mod tests { ]), serde_json::json!({"owner": "owner111", "seed": "seed"}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "derived111"); assert_eq!(result.outputs[0].payload_json["projection"]["baseAccount"], "base111"); assert_eq!(result.outputs[0].payload_json["projection"]["seed"], "seed"); @@ -571,7 +571,7 @@ mod tests { #[test] fn config_store_preserves_bounded_opaque_audit_fields() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; let observation = observation( super::CONFIG_SURFACE, "store", @@ -589,7 +589,7 @@ mod tests { "configDataPrefixHex": "0102", }), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); assert_eq!(result.outputs[0].output_key, "config_account_update:store:0"); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "config111"); assert_eq!(result.outputs[0].payload_json["projection"]["configDataSha256"], "abc"); @@ -598,7 +598,7 @@ mod tests { #[test] fn loader_authority_variants_create_exact_admin_outputs() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; for (surface, entry, target_role) in [ (super::BPF_LOADER_UPGRADEABLE_SURFACE, "set_authority", "authority_target"), ( @@ -619,8 +619,8 @@ mod tests { ]), serde_json::json!({}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "target111"); assert_eq!(result.outputs[0].payload_json["projection"]["newAuthority"], "new111"); } @@ -639,9 +639,9 @@ mod tests { serde_json::json!({"authorityType":"mint_tokens","newAuthority":null}), ); authority.event.program_id = - crate::ProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()); + crate::MdProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()); let authority_result = - crate::EventMaterializer::materialize(&crate::AdminMaterializer, &authority); + crate::MtApiEventMaterializer::materialize(&crate::MtAdminMaterializer, &authority); assert_eq!(authority_result.outputs[0].output_key, "spl_token_authority:set_authority:0"); assert_eq!( authority_result.outputs[0].payload_json["projection"]["stateTransition"], @@ -660,9 +660,9 @@ mod tests { serde_json::json!({"m":2}), ); multisig.event.program_id = - crate::ProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()); + crate::MdProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()); let multisig_result = - crate::EventMaterializer::materialize(&crate::AdminMaterializer, &multisig); + crate::MtApiEventMaterializer::materialize(&crate::MtAdminMaterializer, &multisig); assert_eq!( multisig_result.outputs[0].output_key, "spl_token_multisig:initialize_multisig2:0" @@ -676,9 +676,9 @@ mod tests { } #[test] - fn token_2022_authority_change_uses_the_admin_owner_once() { + fn token2022_authority_change_uses_the_admin_owner_once() { let mut observation = observation( - super::SPL_TOKEN_2022_SURFACE, + super::SPL_TOKEN2022_SURFACE, "set_authority", false, serde_json::json!([ @@ -688,19 +688,20 @@ mod tests { serde_json::json!({"authorityType":"mint_tokens","newAuthority":null}), ); observation.event.program_id = - crate::ProgramId(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.to_string()); - let result = crate::EventMaterializer::materialize(&crate::AdminMaterializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + crate::MdProgramId(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.to_string()); + let result = + crate::MtApiEventMaterializer::materialize(&crate::MtAdminMaterializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs.len(), 1); assert_eq!( result.outputs[0].payload_json["programId"], - kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID ); } #[test] fn failed_admin_mutation_is_refused() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; let observation = observation( super::SYSTEM_SURFACE, "assign", @@ -708,8 +709,8 @@ mod tests { serde_json::json!([account("assigned_account", "account111",)]), serde_json::json!({"owner": "owner111"}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Refused); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); assert!(result.outputs.is_empty()); } @@ -723,20 +724,21 @@ mod tests { serde_json::json!({}), ); observation.event.program_id = - crate::ProgramId(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string()); - observation.event.event_family = crate::EventFamily::Lifecycle; - assert!(!crate::EventMaterializer::accepts_observation( - &crate::AdminMaterializer, + crate::MdProgramId(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string()); + observation.event.event_family = crate::MdEventFamily::Lifecycle; + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &crate::MtAdminMaterializer, &observation, )); - let result = crate::EventMaterializer::materialize(&crate::AdminMaterializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Ignored); + let result = + crate::MtApiEventMaterializer::materialize(&crate::MtAdminMaterializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); assert!(result.outputs.is_empty()); } #[test] fn unrelated_admin_observation_is_ignored() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; let observation = observation( "other_surface", "set_authority", @@ -744,13 +746,13 @@ mod tests { serde_json::json!([]), serde_json::json!({}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Ignored); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); } #[test] fn output_serialization_is_deterministic() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; let observation = observation( super::CONFIG_SURFACE, "store", @@ -765,8 +767,8 @@ mod tests { "configDataPrefixHex": "01", }), ); - let first = crate::EventMaterializer::materialize(&materializer, &observation); - let second = crate::EventMaterializer::materialize(&materializer, &observation); + let first = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + let second = crate::MtApiEventMaterializer::materialize(&materializer, &observation); let first_json = match serde_json::to_string(&first) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => panic!("first admin serialization failed: {error}"), @@ -780,7 +782,7 @@ mod tests { #[test] fn elgamal_registry_create_and_update_have_one_admin_owner() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; for (operation, offset, owner_position, transition) in [ ("create_registry", 1_i64, 1_u64, "elgamal_registry_created"), ("update_registry", 0_i64, 2_u64, "elgamal_registry_key_updated"), @@ -797,8 +799,8 @@ mod tests { ]), serde_json::json!({}), ); - observation.event.program_id = crate::ProgramId( - kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID.to_string(), + observation.event.program_id = crate::MdProgramId( + kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID.to_string(), ); observation.payload_json = serde_json::json!({ "accounts": observation.payload_json["accounts"].clone(), @@ -809,8 +811,8 @@ mod tests { "relative_instruction_offset" }, }); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs.len(), 1); assert_eq!( result.outputs[0].payload_json["projection"]["registryAccount"], @@ -826,7 +828,7 @@ mod tests { #[test] fn elgamal_registry_foreign_program_and_failed_transaction_are_refused() { - let materializer = crate::AdminMaterializer; + let materializer = crate::MtAdminMaterializer; let mut foreign = observation( super::SPL_ELGAMAL_REGISTRY_SURFACE, "create_registry", @@ -835,20 +837,20 @@ mod tests { serde_json::json!({}), ); foreign.event.program_id = - crate::ProgramId(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.to_string()); - assert!(!crate::EventMaterializer::accepts_observation(&materializer, &foreign,)); + crate::MdProgramId(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.to_string()); + assert!(!crate::MtApiEventMaterializer::accepts_observation(&materializer, &foreign,)); let mut failed = foreign.clone(); - failed.event.program_id = crate::ProgramId( - kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID.to_string(), + failed.event.program_id = crate::MdProgramId( + kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID.to_string(), ); failed.transaction_failed = true; failed.observation_committed = false; - let result = crate::EventMaterializer::materialize(&materializer, &failed); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Refused); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &failed); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); } #[test] - fn token_2022_pointer_and_hook_admin_events_have_one_owner() { + fn token2022_pointer_and_hook_admin_events_have_one_owner() { for (operation, field, value) in [ ("initialize_transfer_hook", "programId", "hook111"), ("update_metadata_pointer", "metadataAddress", "metadata111"), @@ -856,18 +858,20 @@ mod tests { ("update_group_member_pointer", "memberAddress", "member111"), ] { let mut observation = observation( - super::SPL_TOKEN_2022_SURFACE, + super::SPL_TOKEN2022_SURFACE, operation, false, serde_json::json!([{"position":0,"accountKey":"mint111"}]), serde_json::json!({(field):value,"authority":"authority111"}), ); - observation.event.event_family = crate::EventFamily::TokenAccount; + observation.event.event_family = crate::MdEventFamily::TokenAccount; observation.event.program_id = - crate::ProgramId(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.to_string()); - let result = - crate::EventMaterializer::materialize(&crate::AdminMaterializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + crate::MdProgramId(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.to_string()); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtAdminMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs.len(), 1); assert_eq!(result.outputs[0].payload_json["projection"][field], value); assert_eq!(result.outputs[0].payload_json["projection"]["stateReadRequired"], true); @@ -875,44 +879,45 @@ mod tests { } #[test] - fn token_2022_extension_admin_rejects_foreign_program_and_failed_transaction() { + fn token2022_extension_admin_rejects_foreign_program_and_failed_transaction() { let mut observation = observation( - super::SPL_TOKEN_2022_SURFACE, + super::SPL_TOKEN2022_SURFACE, "initialize_metadata_pointer", false, serde_json::json!([]), serde_json::json!({"metadataAddress":"metadata111"}), ); - observation.event.event_family = crate::EventFamily::TokenAccount; + observation.event.event_family = crate::MdEventFamily::TokenAccount; observation.event.program_id = - crate::ProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()); - assert!(!crate::EventMaterializer::accepts_observation( - &crate::AdminMaterializer, + crate::MdProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()); + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &crate::MtAdminMaterializer, &observation, )); observation.event.program_id = - crate::ProgramId(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.to_string()); + crate::MdProgramId(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.to_string()); observation.transaction_failed = true; observation.observation_committed = false; - let result = crate::EventMaterializer::materialize(&crate::AdminMaterializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Refused); + let result = + crate::MtApiEventMaterializer::materialize(&crate::MtAdminMaterializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); } } /// Materialize authoritative Token-2022 administrative extension snapshots. -pub fn materialize_token_2022_admin_state_snapshots( +pub fn materialize_token2022_admin_state_snapshots( account_key: &str, slot: u64, - state: &crate::Token2022State, -) -> std::result::Result, String> { + state: &crate::DcToken2022State, +) -> std::result::Result, String> { if account_key.is_empty() { return std::result::Result::Err( "Token-2022 admin state snapshot requires a non-empty account key".to_string(), ); } - if state.kind != crate::Token2022StateKind::Mint { + if state.kind != crate::DcToken2022StateKind::Mint { for entry in &state.extensions { - if is_token_2022_admin_mint_extension(entry.extension_name) { + if is_token2022_admin_mint_extension(entry.extension_name) { return std::result::Result::Err(format!( "Token-2022 {} extension requires mint state", entry.extension_name @@ -923,22 +928,22 @@ pub fn materialize_token_2022_admin_state_snapshots( } let mut outputs = std::vec::Vec::new(); for entry in &state.extensions { - if !is_token_2022_admin_mint_extension(entry.extension_name) { + if !is_token2022_admin_mint_extension(entry.extension_name) { continue; } let output_key = - format!("token_2022_admin_state:{}:{account_key}:{slot}", entry.extension_name); - outputs.push(crate::MaterializedOutput { + format!("token2022_admin_state:{}:{account_key}:{slot}", entry.extension_name); + outputs.push(crate::MtApiMaterializedOutput { output_key: output_key.clone(), - family: crate::MaterializedEventFamily::Admin, + family: crate::MdMaterializedEventFamily::Admin, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "authoritative_bounded_admin_state_snapshot", - "domain": "token_2022_extension_admin_state", + "domain": "token2022_extension_admin_state", "idempotenceKey": output_key, "accountKey": account_key, "slot": slot, - "programId": kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, + "programId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, "stateKind": "mint", "extensionType": entry.extension_type, "extensionName": entry.extension_name, @@ -946,9 +951,9 @@ pub fn materialize_token_2022_admin_state_snapshots( "valueFields": entry.value_fields, "finalAccountStateCaptured": true, "provenance": { - "processorName": crate::MATERIALIZER_ADMIN_PROCESSOR_NAME, + "processorName": crate::MT_ADMIN_PROCESSOR_NAME, "processorVersion": env!("CARGO_PKG_VERSION"), - "source": "exact_token_2022_tlv_state_parser" + "source": "exact_token2022_tlv_state_parser" } }), }); @@ -956,7 +961,7 @@ pub fn materialize_token_2022_admin_state_snapshots( return std::result::Result::Ok(outputs); } -fn is_token_2022_admin_mint_extension(extension_name: &str) -> bool { +fn is_token2022_admin_mint_extension(extension_name: &str) -> bool { return matches!( extension_name, "mint_close_authority" @@ -974,27 +979,27 @@ fn is_token_2022_admin_mint_extension(extension_name: &str) -> bool { } #[cfg(test)] -mod token_2022_admin_state_tests { - fn mint_state() -> crate::Token2022State { - return crate::Token2022State { - kind: crate::Token2022StateKind::Mint, +mod token2022_admin_state_tests { + fn mint_state() -> crate::DcToken2022State { + return crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Mint, base_fields: serde_json::json!({}), base_hex: String::new(), account_type: std::option::Option::Some(1), extensions: vec![ - crate::Token2022TlvEntry { + crate::DcToken2022TlvEntry { extension_type: 6, extension_name: "default_account_state", value_hex: "02".to_string(), value_fields: serde_json::json!({"state": 2}), }, - crate::Token2022TlvEntry { + crate::DcToken2022TlvEntry { extension_type: 26, extension_name: "pausable", value_hex: "00".repeat(33), value_fields: serde_json::json!({"paused": false}), }, - crate::Token2022TlvEntry { + crate::DcToken2022TlvEntry { extension_type: 1, extension_name: "transfer_fee_config", value_hex: "00".to_string(), @@ -1007,8 +1012,8 @@ mod token_2022_admin_state_tests { #[test] fn admin_snapshots_are_owned_once_filtered_and_idempotent() { let state = mint_state(); - let first = crate::materialize_token_2022_admin_state_snapshots("mint111", 44, &state); - let second = crate::materialize_token_2022_admin_state_snapshots("mint111", 44, &state); + let first = crate::materialize_token2022_admin_state_snapshots("mint111", 44, &state); + let second = crate::materialize_token2022_admin_state_snapshots("mint111", 44, &state); assert_eq!(first, second); assert_eq!(first.as_ref().map(std::vec::Vec::len), std::result::Result::Ok(2)); assert_eq!( @@ -1028,35 +1033,35 @@ mod token_2022_admin_state_tests { #[test] fn admin_snapshots_reject_empty_identity_and_wrong_state_kind() { let state = mint_state(); - assert!(crate::materialize_token_2022_admin_state_snapshots("", 44, &state).is_err()); - let account_state = crate::Token2022State { - kind: crate::Token2022StateKind::Account, + assert!(crate::materialize_token2022_admin_state_snapshots("", 44, &state).is_err()); + let account_state = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Account, base_fields: serde_json::json!({}), base_hex: String::new(), account_type: std::option::Option::Some(2), extensions: state.extensions[..1].to_vec(), }; assert!( - crate::materialize_token_2022_admin_state_snapshots("account111", 44, &account_state,) + crate::materialize_token2022_admin_state_snapshots("account111", 44, &account_state,) .is_err() ); } } /// Materialize one authoritative SPL ElGamal registry account snapshot. -pub fn materialize_elgamal_registry_state_snapshot( +pub fn materializer_admin_materialize_elgamal_registry_state_snapshot( registry_account_key: &str, slot: u64, - state: &crate::ElGamalRegistryState, -) -> std::result::Result { + state: &crate::DcSplElGamalRegistryState, +) -> std::result::Result { if registry_account_key.is_empty() { return std::result::Result::Err( "SPL ElGamal registry snapshot requires a non-empty account key".to_string(), ); } - return std::result::Result::Ok(crate::MaterializedOutput { + return std::result::Result::Ok(crate::MtApiMaterializedOutput { output_key: format!("spl_elgamal_registry_state:{registry_account_key}:{slot}"), - family: crate::MaterializedEventFamily::Admin, + family: crate::MdMaterializedEventFamily::Admin, payload_json: serde_json::json!({ "projectionVersion": 1, "domain": "spl_elgamal_registry_account_state", @@ -1064,7 +1069,7 @@ pub fn materialize_elgamal_registry_state_snapshot( "idempotenceKey": format!("spl_elgamal_registry:{registry_account_key}:{slot}"), "registryAccountKey": registry_account_key, "slot": slot, - "programId": kb_program_ids::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, + "programId": kb_program_ids::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, "owner": state.owner, "elgamalPubkeyBase64": state.elgamal_pubkey_base64, "wireHex": state.wire_hex, @@ -1072,7 +1077,7 @@ pub fn materialize_elgamal_registry_state_snapshot( "confidentialValuesDecrypted": false, "finalAccountStateCaptured": true, "provenance": { - "processorName": crate::MATERIALIZER_ADMIN_PROCESSOR_NAME, + "processorName": crate::MT_ADMIN_PROCESSOR_NAME, "processorVersion": env!("CARGO_PKG_VERSION"), "source": "exact_spl_elgamal_registry_state_parser" } @@ -1084,12 +1089,16 @@ pub fn materialize_elgamal_registry_state_snapshot( mod elgamal_registry_state_tests { #[test] fn exact_registry_snapshot_preserves_public_state_without_claiming_proof_validation() { - let state = crate::ElGamalRegistryState { + let state = crate::DcSplElGamalRegistryState { owner: "owner111".to_string(), elgamal_pubkey_base64: "AQID".to_string(), wire_hex: "00".repeat(64), }; - let output = crate::materialize_elgamal_registry_state_snapshot("registry111", 11, &state); + let output = crate::materializer_admin_materialize_elgamal_registry_state_snapshot( + "registry111", + 11, + &state, + ); assert_eq!( output.as_ref().map(|value| return value.payload_json["owner"].clone()), std::result::Result::Ok(serde_json::json!("owner111")) @@ -1111,14 +1120,25 @@ mod elgamal_registry_state_tests { #[test] fn registry_snapshot_is_idempotent_and_requires_account_identity() { - let state = crate::ElGamalRegistryState { + let state = crate::DcSplElGamalRegistryState { owner: "owner111".to_string(), elgamal_pubkey_base64: "AQID".to_string(), wire_hex: "00".repeat(64), }; - let first = crate::materialize_elgamal_registry_state_snapshot("registry111", 11, &state); - let second = crate::materialize_elgamal_registry_state_snapshot("registry111", 11, &state); + let first = crate::materializer_admin_materialize_elgamal_registry_state_snapshot( + "registry111", + 11, + &state, + ); + let second = crate::materializer_admin_materialize_elgamal_registry_state_snapshot( + "registry111", + 11, + &state, + ); assert_eq!(first, second); - assert!(crate::materialize_elgamal_registry_state_snapshot("", 11, &state).is_err()); + assert!( + crate::materializer_admin_materialize_elgamal_registry_state_snapshot("", 11, &state) + .is_err() + ); } } diff --git a/kb-lib/src/materializer/api.rs b/kb-lib/src/materializer/api.rs index 8745290..089a132 100644 --- a/kb-lib/src/materializer/api.rs +++ b/kb-lib/src/materializer/api.rs @@ -1,31 +1,32 @@ // file: kb-lib/src/materializer/api.rs -// version: 2 +// version: 3 //! Materializer contracts consolidated from `kb_materializer_api`. -pub mod contracts; -pub mod materializer; +mod contracts; +mod materializer; + /// Stable decoded observation materializer contract used by the common pipeline. -pub use crate::materializer::api::contracts::EventMaterializer; +pub use self::contracts::MtApiEventMaterializer; /// Explicit policy applied to successful and failed source transactions. -pub use crate::materializer::api::contracts::MaterializationTransactionPolicy; +pub use self::contracts::MtApiMaterializationTransactionPolicy; /// Stable processor-owned business output derived from one decoded observation. -pub use crate::materializer::api::contracts::MaterializedOutput; +pub use self::contracts::MtApiMaterializedOutput; /// Structured materializer diagnostic without generic error wrappers. -pub use crate::materializer::api::contracts::MaterializerDiagnostic; +pub use self::contracts::MtApiMaterializerDiagnostic; /// Complete explicit result produced by one materializer invocation. -pub use crate::materializer::api::contracts::MaterializerExecutionResult; +pub use self::contracts::MtApiMaterializerExecutionResult; /// Stable identity of one decoded event materializer. -pub use crate::materializer::api::contracts::MaterializerIdentity; +pub use self::contracts::MtApiMaterializerIdentity; /// Terminal materializer result status. -pub use crate::materializer::api::contracts::MaterializerOutcomeStatus; +pub use self::contracts::MtApiMaterializerOutcomeStatus; /// Returns true when a materializer explicitly accepts one decoded family. -pub use crate::materializer::api::contracts::materializer_accepts_family; +pub use self::contracts::materializer_api_accepts_family; /// Returns true when a materializer accepts one exact decoded observation. -pub use crate::materializer::api::contracts::materializer_accepts_observation; +pub use self::contracts::materializer_api_accepts_observation; /// Applies the mandatory source transaction policy before materialization. -pub use crate::materializer::api::contracts::validate_materialization_policy; +pub use self::contracts::materializer_api_validate_materialization_policy; /// Rejects mutable business outputs derived from failed or uncommitted observations. -pub use crate::materializer::api::contracts::validate_materialized_output_policy; +pub use self::contracts::materializer_api_validate_materialized_output_policy; /// Exposes the legacy common business materializer trait. -pub use crate::materializer::api::materializer::Materializer; +pub use self::materializer::MtMaterializer; diff --git a/kb-lib/src/materializer/api/contracts.rs b/kb-lib/src/materializer/api/contracts.rs index b449f61..c6aaf9c 100644 --- a/kb-lib/src/materializer/api/contracts.rs +++ b/kb-lib/src/materializer/api/contracts.rs @@ -5,14 +5,14 @@ /// Stable identity of one decoded event materializer. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct MaterializerIdentity { +pub struct MtApiMaterializerIdentity { /// Stable lower snake case processor name. pub name: std::string::String, /// Semantic or deterministic implementation version. pub version: std::string::String, } -impl MaterializerIdentity { +impl MtApiMaterializerIdentity { /// Builds a validated materializer identity. pub fn new( name: impl std::convert::Into, @@ -33,7 +33,7 @@ impl MaterializerIdentity { /// Explicit policy applied to successful and failed source transactions. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub enum MaterializationTransactionPolicy { +pub enum MtApiMaterializationTransactionPolicy { /// Accept committed observations from successful transactions only. SuccessfulCommittedOnly, /// Accept successful observations and failed audit-only observations. @@ -44,7 +44,7 @@ pub enum MaterializationTransactionPolicy { /// Terminal materializer result status. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub enum MaterializerOutcomeStatus { +pub enum MtApiMaterializerOutcomeStatus { /// One or more new stable outputs were inserted. Inserted, /// One or more processor-owned outputs were deterministically replaced. @@ -59,7 +59,7 @@ pub enum MaterializerOutcomeStatus { /// Structured materializer diagnostic without generic error wrappers. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct MaterializerDiagnostic { +pub struct MtApiMaterializerDiagnostic { /// Stable machine-readable diagnostic code. pub code: std::string::String, /// Human-readable diagnostic message. @@ -68,7 +68,7 @@ pub struct MaterializerDiagnostic { pub retriable: bool, } -impl MaterializerDiagnostic { +impl MtApiMaterializerDiagnostic { /// Builds a validated materializer diagnostic. pub fn new( code: impl std::convert::Into, @@ -91,16 +91,16 @@ impl MaterializerDiagnostic { /// Stable processor-owned business output derived from one decoded observation. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct MaterializedOutput { +pub struct MtApiMaterializedOutput { /// Stable processor-owned output key within one decoded observation. pub output_key: std::string::String, /// Business output family. - pub family: crate::MaterializedEventFamily, + pub family: crate::MdMaterializedEventFamily, /// Typed business payload serialized as deterministic JSON. pub payload_json: serde_json::Value, } -impl MaterializedOutput { +impl MtApiMaterializedOutput { /// Validates stable output identity. pub fn validate(&self) -> kb_core::Result<()> { if self.output_key.trim().is_empty() { @@ -114,22 +114,22 @@ impl MaterializedOutput { /// Complete explicit result produced by one materializer invocation. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct MaterializerExecutionResult { +pub struct MtApiMaterializerExecutionResult { /// Terminal materializer status. - pub status: MaterializerOutcomeStatus, + pub status: MtApiMaterializerOutcomeStatus, /// Stable business outputs. - pub outputs: std::vec::Vec, + pub outputs: std::vec::Vec, /// Structured diagnostics. - pub diagnostics: std::vec::Vec, + pub diagnostics: std::vec::Vec, } -impl MaterializerExecutionResult { +impl MtApiMaterializerExecutionResult { /// Builds a policy refusal result. pub fn refused(code: &str, message: &str) -> Self { return Self { - status: MaterializerOutcomeStatus::Refused, + status: MtApiMaterializerOutcomeStatus::Refused, outputs: std::vec::Vec::new(), - diagnostics: std::vec![MaterializerDiagnostic { + diagnostics: std::vec![MtApiMaterializerDiagnostic { code: code.to_string(), message: message.to_string(), retriable: false, @@ -140,7 +140,7 @@ impl MaterializerExecutionResult { /// Builds an ignored result. pub fn ignored() -> Self { return Self { - status: MaterializerOutcomeStatus::Ignored, + status: MtApiMaterializerOutcomeStatus::Ignored, outputs: std::vec::Vec::new(), diagnostics: std::vec::Vec::new(), }; @@ -148,8 +148,8 @@ impl MaterializerExecutionResult { /// Validates status and output consistency. pub fn validate(&self) -> kb_core::Result<()> { - let output_status = self.status == MaterializerOutcomeStatus::Inserted - || self.status == MaterializerOutcomeStatus::Replaced; + let output_status = self.status == MtApiMaterializerOutcomeStatus::Inserted + || self.status == MtApiMaterializerOutcomeStatus::Replaced; if output_status && self.outputs.is_empty() { return std::result::Result::Err(kb_core::Error::invalid_state( "inserted or replaced materializer status requires outputs", @@ -160,7 +160,7 @@ impl MaterializerExecutionResult { "ignored, refused or failed materializer status must not contain outputs", )); } - if self.status == MaterializerOutcomeStatus::Failed && self.diagnostics.is_empty() { + if self.status == MtApiMaterializerOutcomeStatus::Failed && self.diagnostics.is_empty() { return std::result::Result::Err(kb_core::Error::invalid_state( "failed materializer status requires at least one diagnostic", )); @@ -176,26 +176,32 @@ impl MaterializerExecutionResult { } /// Stable decoded observation materializer contract used by the common pipeline. -pub trait EventMaterializer: std::marker::Send + std::marker::Sync { +pub trait MtApiEventMaterializer: std::marker::Send + std::marker::Sync { /// Returns the stable materializer identity. - fn identity(&self) -> MaterializerIdentity; + fn identity(&self) -> MtApiMaterializerIdentity; /// Returns every decoded event family explicitly accepted by this materializer. - fn accepted_families(&self) -> &'static [crate::EventFamily]; + fn accepted_families(&self) -> &'static [crate::MdEventFamily]; /// Returns whether this materializer accepts one exact decoded observation. - fn accepts_observation(&self, observation: &crate::DecodedObservation) -> bool { + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { let family = observation.event.event_family; return self.accepted_families().iter().any(|accepted| return *accepted == family); } /// Returns the failed/successful transaction policy for one accepted family. - fn transaction_policy(&self, family: crate::EventFamily) -> MaterializationTransactionPolicy; + fn transaction_policy( + &self, + family: crate::MdEventFamily, + ) -> MtApiMaterializationTransactionPolicy; /// Materializes one validated decoded observation. - fn materialize(&self, observation: &crate::DecodedObservation) -> MaterializerExecutionResult; + fn materialize( + &self, + observation: &crate::DcApiDecodedObservation, + ) -> MtApiMaterializerExecutionResult; } /// Returns true when a materializer explicitly accepts one decoded family. -pub fn materializer_accepts_family( - materializer: &dyn EventMaterializer, - family: crate::EventFamily, +pub fn materializer_api_accepts_family( + materializer: &dyn MtApiEventMaterializer, + family: crate::MdEventFamily, ) -> bool { return materializer .accepted_families() @@ -204,48 +210,48 @@ pub fn materializer_accepts_family( } /// Returns true when a materializer accepts one exact decoded observation. -pub fn materializer_accepts_observation( - materializer: &dyn EventMaterializer, - observation: &crate::DecodedObservation, +pub fn materializer_api_accepts_observation( + materializer: &dyn MtApiEventMaterializer, + observation: &crate::DcApiDecodedObservation, ) -> bool { return materializer.accepts_observation(observation); } /// Applies the mandatory source transaction policy before materialization. -pub fn validate_materialization_policy( - materializer: &dyn EventMaterializer, - observation: &crate::DecodedObservation, -) -> std::result::Result<(), MaterializerExecutionResult> { +pub fn materializer_api_validate_materialization_policy( + materializer: &dyn MtApiEventMaterializer, + observation: &crate::DcApiDecodedObservation, +) -> std::result::Result<(), MtApiMaterializerExecutionResult> { let family = observation.event.event_family; - if !crate::materializer_accepts_observation(materializer, observation) { - return std::result::Result::Err(MaterializerExecutionResult::refused( + if !crate::materializer_api_accepts_observation(materializer, observation) { + return std::result::Result::Err(MtApiMaterializerExecutionResult::refused( "unsupported_decoded_observation", "materializer does not accept the decoded observation surface and entry", )); } let policy = materializer.transaction_policy(family); if observation.transaction_failed || !observation.observation_committed { - if family == crate::EventFamily::Trade - || family == crate::EventFamily::Liquidity - || family == crate::EventFamily::Lifecycle + if family == crate::MdEventFamily::Trade + || family == crate::MdEventFamily::Liquidity + || family == crate::MdEventFamily::Lifecycle { - return std::result::Result::Err(MaterializerExecutionResult::refused( + return std::result::Result::Err(MtApiMaterializerExecutionResult::refused( "failed_transaction_mutation_refused", "failed or uncommitted observations cannot create successful mutable business outputs", )); } - if policy == MaterializationTransactionPolicy::SuccessfulCommittedOnly { - return std::result::Result::Err(MaterializerExecutionResult::refused( + if policy == MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly { + return std::result::Result::Err(MtApiMaterializerExecutionResult::refused( "failed_transaction_policy_refused", "materializer accepts committed observations from successful transactions only", )); } - if policy == MaterializationTransactionPolicy::SuccessfulOrFailedAudit - && family != crate::EventFamily::Audit - && family != crate::EventFamily::ComplianceAudit - && family != crate::EventFamily::Risk + if policy == MtApiMaterializationTransactionPolicy::SuccessfulOrFailedAudit + && family != crate::MdEventFamily::Audit + && family != crate::MdEventFamily::ComplianceAudit + && family != crate::MdEventFamily::Risk { - return std::result::Result::Err(MaterializerExecutionResult::refused( + return std::result::Result::Err(MtApiMaterializerExecutionResult::refused( "failed_transaction_non_audit_refused", "failed transaction materialization is limited to declared audit or risk families", )); @@ -255,20 +261,20 @@ pub fn validate_materialization_policy( } /// Rejects successful mutable business outputs derived from failed or uncommitted observations. -pub fn validate_materialized_output_policy( - observation: &crate::DecodedObservation, - result: &MaterializerExecutionResult, -) -> std::result::Result<(), MaterializerExecutionResult> { +pub fn materializer_api_validate_materialized_output_policy( + observation: &crate::DcApiDecodedObservation, + result: &MtApiMaterializerExecutionResult, +) -> std::result::Result<(), MtApiMaterializerExecutionResult> { if !observation.transaction_failed && observation.observation_committed { return std::result::Result::Ok(()); } let forbidden_output = result.outputs.iter().any(|output| { - return output.family != crate::MaterializedEventFamily::ComplianceAudit - && output.family != crate::MaterializedEventFamily::TokenMetadataRisk - && output.family != crate::MaterializedEventFamily::Risk; + return output.family != crate::MdMaterializedEventFamily::ComplianceAudit + && output.family != crate::MdMaterializedEventFamily::TokenMetadataRisk + && output.family != crate::MdMaterializedEventFamily::Risk; }); if forbidden_output { - return std::result::Result::Err(MaterializerExecutionResult::refused( + return std::result::Result::Err(MtApiMaterializerExecutionResult::refused( "failed_transaction_output_refused", "failed or uncommitted observations may only produce audit or risk outputs", )); @@ -280,48 +286,48 @@ pub fn validate_materialized_output_policy( mod tests { struct TradeMaterializer; - impl crate::EventMaterializer for TradeMaterializer { - fn identity(&self) -> crate::MaterializerIdentity { - return crate::MaterializerIdentity { + impl crate::MtApiEventMaterializer for TradeMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { name: "trade_materializer".to_string(), version: "1".to_string(), }; } - fn accepted_families(&self) -> &'static [crate::EventFamily] { - return &[crate::EventFamily::Trade]; + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { + return &[crate::MdEventFamily::Trade]; } fn transaction_policy( &self, - _family: crate::EventFamily, - ) -> crate::MaterializationTransactionPolicy { - return crate::MaterializationTransactionPolicy::SuccessfulCommittedOnly; + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; } fn materialize( &self, - _observation: &crate::DecodedObservation, - ) -> crate::MaterializerExecutionResult { - return crate::MaterializerExecutionResult::ignored(); + _observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { + return crate::MtApiMaterializerExecutionResult::ignored(); } } - fn failed_trade_observation() -> crate::DecodedObservation { - return crate::DecodedObservation { + fn failed_trade_observation() -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { event_key: "trade".to_string(), - event: crate::DecodedProtocolEvent { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(42), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId("program".to_string()), - protocol_code: crate::ProtocolCode("protocol".to_string()), - surface_code: crate::SurfaceCode("surface".to_string()), - event_code: crate::EventCode("trade".to_string()), - event_name: crate::EventName("trade".to_string()), - event_family: crate::EventFamily::Trade, - source_kind: crate::EventSourceKind::Instruction, - confidence: crate::DecoderConfidence::Exact, + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId("program".to_string()), + protocol_code: crate::MdProtocolCode("protocol".to_string()), + surface_code: crate::MdSurfaceCode("surface".to_string()), + event_code: crate::MdEventCode("trade".to_string()), + event_name: crate::MdEventName("trade".to_string()), + event_family: crate::MdEventFamily::Trade, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::Exact, }, payload_json: serde_json::json!({}), transaction_failed: true, @@ -329,9 +335,9 @@ mod tests { serde_json::json!({"InstructionError": [0, "Custom"]}), ), observation_committed: false, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::ExactLayout, - confidence: crate::DecoderConfidence::Exact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::ExactLayout, + confidence: crate::MdDecoderConfidence::Exact, evidence: std::vec!["layout".to_string()], }, }; @@ -339,47 +345,49 @@ mod tests { #[test] fn failed_trade_is_refused_before_materialization() { - let result = - crate::validate_materialization_policy(&TradeMaterializer, &failed_trade_observation()); + let result = crate::materializer_api_validate_materialization_policy( + &TradeMaterializer, + &failed_trade_observation(), + ); assert!(result.is_err()); let refusal = match result { std::result::Result::Ok(()) => panic!("failed trade unexpectedly accepted"), std::result::Result::Err(value) => value, }; - assert_eq!(refusal.status, crate::MaterializerOutcomeStatus::Refused); + assert_eq!(refusal.status, crate::MtApiMaterializerOutcomeStatus::Refused); assert_eq!(refusal.diagnostics[0].code, "failed_transaction_mutation_refused"); } struct FailedAuditToTradeMaterializer; - impl crate::EventMaterializer for FailedAuditToTradeMaterializer { - fn identity(&self) -> crate::MaterializerIdentity { - return crate::MaterializerIdentity { + impl crate::MtApiEventMaterializer for FailedAuditToTradeMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { name: "failed_audit_to_trade".to_string(), version: "1".to_string(), }; } - fn accepted_families(&self) -> &'static [crate::EventFamily] { - return &[crate::EventFamily::Audit]; + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { + return &[crate::MdEventFamily::Audit]; } fn transaction_policy( &self, - _family: crate::EventFamily, - ) -> crate::MaterializationTransactionPolicy { - return crate::MaterializationTransactionPolicy::SuccessfulOrFailedAudit; + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulOrFailedAudit; } fn materialize( &self, - _observation: &crate::DecodedObservation, - ) -> crate::MaterializerExecutionResult { - return crate::MaterializerExecutionResult { - status: crate::MaterializerOutcomeStatus::Inserted, - outputs: std::vec![crate::MaterializedOutput { + _observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, + outputs: std::vec![crate::MtApiMaterializedOutput { output_key: "trade".to_string(), - family: crate::MaterializedEventFamily::Trade, + family: crate::MdMaterializedEventFamily::Trade, payload_json: serde_json::json!({}), }], diagnostics: std::vec::Vec::new(), @@ -387,9 +395,9 @@ mod tests { } } - fn failed_audit_observation() -> crate::DecodedObservation { + fn failed_audit_observation() -> crate::DcApiDecodedObservation { let mut observation = failed_trade_observation(); - observation.event.event_family = crate::EventFamily::Audit; + observation.event.event_family = crate::MdEventFamily::Audit; return observation; } @@ -397,16 +405,20 @@ mod tests { fn failed_audit_cannot_emit_successful_trade_output() { let materializer = FailedAuditToTradeMaterializer; let observation = failed_audit_observation(); - let policy_result = crate::validate_materialization_policy(&materializer, &observation); + let policy_result = + crate::materializer_api_validate_materialization_policy(&materializer, &observation); assert!(policy_result.is_ok()); - let materialized = crate::EventMaterializer::materialize(&materializer, &observation); - let output_result = crate::validate_materialized_output_policy(&observation, &materialized); + let materialized = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + let output_result = crate::materializer_api_validate_materialized_output_policy( + &observation, + &materialized, + ); assert!(output_result.is_err()); let refusal = match output_result { std::result::Result::Ok(()) => panic!("failed audit unexpectedly emitted a trade"), std::result::Result::Err(value) => value, }; - assert_eq!(refusal.status, crate::MaterializerOutcomeStatus::Refused); + assert_eq!(refusal.status, crate::MtApiMaterializerOutcomeStatus::Refused); assert_eq!(refusal.diagnostics[0].code, "failed_transaction_output_refused"); } } diff --git a/kb-lib/src/materializer/api/materializer.rs b/kb-lib/src/materializer/api/materializer.rs index 71d6685..9150fbd 100644 --- a/kb-lib/src/materializer/api/materializer.rs +++ b/kb-lib/src/materializer/api/materializer.rs @@ -4,7 +4,7 @@ //! Materializer API contract used by business materializer crates. /// Common contract implemented by all business materializer crates. -pub trait Materializer { +pub trait MtMaterializer { /// Returns the stable materializer name. fn materializer_name(&self) -> &'static str; @@ -12,11 +12,11 @@ pub trait Materializer { fn materializer_version(&self) -> &'static str; /// Tests whether this materializer accepts a decoded event. - fn accepts_event(&self, event: &crate::DecodedProtocolEvent) -> bool; + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool; /// Materializes a decoded event into zero or more business events. fn materialize_event( &self, - event: &crate::DecodedProtocolEvent, - ) -> kb_core::Result>; + event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result>; } diff --git a/kb-lib/src/materializer/bridge.rs b/kb-lib/src/materializer/bridge.rs index c9b771e..9ff6fc8 100644 --- a/kb-lib/src/materializer/bridge.rs +++ b/kb-lib/src/materializer/bridge.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/bridge.rs -// version: 1 +// version: 2 //! `bridge` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/bridge/core.rs b/kb-lib/src/materializer/bridge/core.rs index 9516200..db7aa56 100644 --- a/kb-lib/src/materializer/bridge/core.rs +++ b/kb-lib/src/materializer/bridge/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/bridge/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_bridge`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_bridge"; +const LEGACY_CRATE: &str = "kb_materializer_bridge"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/compliance.rs b/kb-lib/src/materializer/compliance.rs index c113c94..0f13a53 100644 --- a/kb-lib/src/materializer/compliance.rs +++ b/kb-lib/src/materializer/compliance.rs @@ -1,12 +1,13 @@ // file: kb-lib/src/materializer/compliance.rs -// version: 2 +// version: 3 //! `compliance` materializer family. -pub mod audit; +mod audit; mod constants; -pub(crate) use crate::materializer::compliance::constants::TRACING_TARGET as MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET; +/// Canonical tracing target for the native compliance audit materializer. +pub(crate) use self::constants::MT_COMPLIANCE_AUDIT_TRACING_TARGET; /// Stable native compliance audit materializer. -pub use crate::materializer::compliance::audit::ComplianceAuditMaterializer; +pub use self::audit::MtComplianceAuditMaterializer; diff --git a/kb-lib/src/materializer/compliance/audit.rs b/kb-lib/src/materializer/compliance/audit.rs index a5c6068..4da25d6 100644 --- a/kb-lib/src/materializer/compliance/audit.rs +++ b/kb-lib/src/materializer/compliance/audit.rs @@ -3,7 +3,7 @@ //! Stable compliance-audit projections for committed native bytecode mutations and execution profiles. -const ACCEPTED_FAMILIES: &[crate::EventFamily] = &[crate::EventFamily::Audit]; +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[crate::MdEventFamily::Audit]; const COMPUTE_BUDGET_SURFACE: &str = "solana_native_compute_budget"; const COMPUTE_BUDGET_ENTRIES: &[&str] = &[ "request_units_deprecated", @@ -47,9 +47,9 @@ impl ProjectionKind { /// Stable compliance-audit materializer for native bytecode mutations and execution profiles. #[derive(Clone, Debug, Default)] -pub struct ComplianceAuditMaterializer; +pub struct MtComplianceAuditMaterializer; -impl crate::Materializer for crate::ComplianceAuditMaterializer { +impl crate::MtMaterializer for crate::MtComplianceAuditMaterializer { fn materializer_name(&self) -> &'static str { return "kb_materializer_compliance_audit"; } @@ -58,36 +58,36 @@ impl crate::Materializer for crate::ComplianceAuditMaterializer { return env!("CARGO_PKG_VERSION"); } - fn accepts_event(&self, event: &crate::DecodedProtocolEvent) -> bool { - return event.event_family == crate::EventFamily::Audit + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { + return event.event_family == crate::MdEventFamily::Audit && projection(event.surface_code.0.as_str(), event.event_name.0.as_str()).is_some(); } fn materialize_event( &self, - event: &crate::DecodedProtocolEvent, - ) -> kb_core::Result> { - if !crate::Materializer::accepts_event(self, event) { + event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + if !crate::MtMaterializer::accepts_event(self, event) { return std::result::Result::Ok(std::vec::Vec::new()); } return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { - fn identity(&self) -> crate::MaterializerIdentity { - return crate::MaterializerIdentity { +impl crate::MtApiEventMaterializer for crate::MtComplianceAuditMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { name: "solana_native_compliance_audit".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn accepted_families(&self) -> &'static [crate::EventFamily] { + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { return ACCEPTED_FAMILIES; } - fn accepts_observation(&self, observation: &crate::DecodedObservation) -> bool { - return observation.event.event_family == crate::EventFamily::Audit + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { + return observation.event.event_family == crate::MdEventFamily::Audit && projection( observation.event.surface_code.0.as_str(), observation.event.event_name.0.as_str(), @@ -97,15 +97,15 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { fn transaction_policy( &self, - _family: crate::EventFamily, - ) -> crate::MaterializationTransactionPolicy { - return crate::MaterializationTransactionPolicy::SuccessfulOrFailedAudit; + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulOrFailedAudit; } fn materialize( &self, - observation: &crate::DecodedObservation, - ) -> crate::MaterializerExecutionResult { + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { let projection = match projection( observation.event.surface_code.0.as_str(), observation.event.event_name.0.as_str(), @@ -113,24 +113,24 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { std::option::Option::Some(value) => value, std::option::Option::None => { tracing::debug!( - target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET, + target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET, action = "materialize_compliance_audit", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), accepted = false, "ignore observation outside supported native compliance-audit projections" ); - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); }, }; - if observation.event.event_family != crate::EventFamily::Audit { - return crate::MaterializerExecutionResult::ignored(); + if observation.event.event_family != crate::MdEventFamily::Audit { + return crate::MtApiMaterializerExecutionResult::ignored(); } if projection != ProjectionKind::ComputeBudgetProfile && (observation.transaction_failed || !observation.observation_committed) { tracing::debug!( - target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET, + target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET, action = "materialize_compliance_audit", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -138,7 +138,7 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { transaction_failed = observation.transaction_failed, "refuse uncommitted native bytecode mutation observation" ); - return crate::MaterializerExecutionResult::refused( + return crate::MtApiMaterializerExecutionResult::refused( "failed_transaction_compliance_audit_refused", "failed or uncommitted native observations cannot create committed bytecode mutation outputs", ); @@ -157,10 +157,10 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { if projection == ProjectionKind::ComputeBudgetProfile { return materialize_compute_budget_profile(observation, parameters, operation); } - let output = crate::MaterializedOutput { + let output = crate::MtApiMaterializedOutput { output_key: projection .output_key(observation.event.surface_code.0.as_str(), operation.as_str()), - family: crate::MaterializedEventFamily::ComplianceAudit, + family: crate::MdMaterializedEventFamily::ComplianceAudit, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "committed_instruction_compliance_audit_event", @@ -178,7 +178,7 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { }), }; tracing::debug!( - target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET, + target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET, action = "materialize_compliance_audit", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -186,8 +186,8 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { output_count = 1_usize, "materialize committed native bytecode mutation observation" ); - return crate::MaterializerExecutionResult { - status: crate::MaterializerOutcomeStatus::Inserted, + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, outputs: std::vec![output], diagnostics: std::vec::Vec::new(), }; @@ -195,17 +195,17 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer { } fn materialize_compute_budget_profile( - observation: &crate::DecodedObservation, + observation: &crate::DcApiDecodedObservation, parameters: serde_json::Value, operation: std::string::String, -) -> crate::MaterializerExecutionResult { +) -> crate::MtApiMaterializerExecutionResult { let profile = parameters.get("transactionProfile").cloned().unwrap_or(serde_json::Value::Null); if !compute_budget_profile_emits(&profile) { - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); } - let output = crate::MaterializedOutput { + let output = crate::MtApiMaterializedOutput { output_key: "transaction_compute_budget_profile:0".to_string(), - family: crate::MaterializedEventFamily::ComplianceAudit, + family: crate::MdMaterializedEventFamily::ComplianceAudit, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "transaction_compute_budget_profile", @@ -225,7 +225,7 @@ fn materialize_compute_budget_profile( }), }; tracing::debug!( - target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET, + target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET, action = "materialize_compute_budget_profile", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -233,8 +233,8 @@ fn materialize_compute_budget_profile( transaction_failed = observation.transaction_failed, "materialize native Compute Budget transaction profile" ); - return crate::MaterializerExecutionResult { - status: crate::MaterializerOutcomeStatus::Inserted, + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, outputs: std::vec![output], diagnostics: std::vec::Vec::new(), }; @@ -349,21 +349,21 @@ mod tests { transaction_failed: bool, accounts: serde_json::Value, parameters: serde_json::Value, - ) -> crate::DecodedObservation { - return crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { event_key: format!("{entry_code}:0"), - event: crate::DecodedProtocolEvent { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(42), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId("program-id".to_string()), - protocol_code: crate::ProtocolCode("solana_native".to_string()), - surface_code: crate::SurfaceCode(surface_code.to_string()), - event_code: crate::EventCode(format!("{surface_code}.{entry_code}")), - event_name: crate::EventName(entry_code.to_string()), - event_family: crate::EventFamily::Audit, - source_kind: crate::EventSourceKind::Instruction, - confidence: crate::DecoderConfidence::ManualExact, + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId("program-id".to_string()), + protocol_code: crate::MdProtocolCode("solana_native".to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")), + event_name: crate::MdEventName(entry_code.to_string()), + event_family: crate::MdEventFamily::Audit, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, }, payload_json: serde_json::json!({"accounts": accounts, "parameters": parameters}), transaction_failed, @@ -373,9 +373,9 @@ mod tests { std::option::Option::None }, observation_committed: !transaction_failed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec!["fixture".to_string()], }, }; @@ -387,7 +387,7 @@ mod tests { #[test] fn loader_write_variants_create_bounded_code_audits() { - let materializer = crate::ComplianceAuditMaterializer; + let materializer = crate::MtComplianceAuditMaterializer; for (surface, target_role, authority_role) in [ (super::BPF_LOADER_DEPRECATED_SURFACE, "program_account", "missing"), (super::BPF_LOADER_SURFACE, "program_account", "missing"), @@ -409,9 +409,9 @@ mod tests { "bytesPrefixHex": "0102", }), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); - assert_eq!(result.outputs[0].family, crate::MaterializedEventFamily::ComplianceAudit); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs[0].family, crate::MdMaterializedEventFamily::ComplianceAudit); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "target111"); assert_eq!(result.outputs[0].payload_json["projection"]["bytesSha256"], "abc"); assert_eq!( @@ -423,7 +423,7 @@ mod tests { #[test] fn loader_v4_copy_preserves_source_and_bounded_ranges() { - let materializer = crate::ComplianceAuditMaterializer; + let materializer = crate::MtComplianceAuditMaterializer; let observation = observation( super::LOADER_V4_SURFACE, "copy", @@ -435,7 +435,7 @@ mod tests { ]), serde_json::json!({"destinationOffset": 8, "sourceOffset": 4, "length": 16}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); assert_eq!( result.outputs[0].output_key, "program_loader_code:solana_native_loader_v4:copy:0" @@ -449,7 +449,7 @@ mod tests { #[test] fn compute_budget_profile_is_emitted_only_by_profile_emitter() { - let materializer = crate::ComplianceAuditMaterializer; + let materializer = crate::MtComplianceAuditMaterializer; let emitter = observation( super::COMPUTE_BUDGET_SURFACE, "set_compute_unit_limit", @@ -469,10 +469,10 @@ mod tests { } }), ); - let emitted = crate::EventMaterializer::materialize(&materializer, &emitter); - assert_eq!(emitted.status, crate::MaterializerOutcomeStatus::Inserted); + let emitted = crate::MtApiEventMaterializer::materialize(&materializer, &emitter); + assert_eq!(emitted.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(emitted.outputs[0].output_key, "transaction_compute_budget_profile:0"); - assert_eq!(emitted.outputs[0].family, crate::MaterializedEventFamily::ComplianceAudit); + assert_eq!(emitted.outputs[0].family, crate::MdMaterializedEventFamily::ComplianceAudit); assert_eq!(emitted.outputs[0].payload_json["profile"]["computeBudgetInstructionCount"], 2); let non_emitter = observation( super::COMPUTE_BUDGET_SURFACE, @@ -486,13 +486,13 @@ mod tests { } }), ); - let ignored = crate::EventMaterializer::materialize(&materializer, &non_emitter); - assert_eq!(ignored.status, crate::MaterializerOutcomeStatus::Ignored); + let ignored = crate::MtApiEventMaterializer::materialize(&materializer, &non_emitter); + assert_eq!(ignored.status, crate::MtApiMaterializerOutcomeStatus::Ignored); } #[test] fn failed_compute_budget_profile_remains_audit_materializable() { - let materializer = crate::ComplianceAuditMaterializer; + let materializer = crate::MtComplianceAuditMaterializer; let observation = observation( super::COMPUTE_BUDGET_SURFACE, "set_compute_unit_price", @@ -506,14 +506,14 @@ mod tests { } }), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].payload_json["transactionSucceeded"], false); } #[test] fn failed_code_mutation_is_refused() { - let materializer = crate::ComplianceAuditMaterializer; + let materializer = crate::MtComplianceAuditMaterializer; let observation = observation( super::LOADER_V4_SURFACE, "write", @@ -521,14 +521,14 @@ mod tests { serde_json::json!([account("program_account", "target111")]), serde_json::json!({"offset": 0, "byteLength": 1, "bytesSha256": "abc"}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Refused); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); assert!(result.outputs.is_empty()); } #[test] fn unrelated_audit_observation_is_ignored() { - let materializer = crate::ComplianceAuditMaterializer; + let materializer = crate::MtComplianceAuditMaterializer; let observation = observation( "other_surface", "write", @@ -536,13 +536,13 @@ mod tests { serde_json::json!([]), serde_json::json!({}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Ignored); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); } #[test] fn output_serialization_is_deterministic() { - let materializer = crate::ComplianceAuditMaterializer; + let materializer = crate::MtComplianceAuditMaterializer; let observation = observation( super::BPF_LOADER_UPGRADEABLE_SURFACE, "write", @@ -558,8 +558,8 @@ mod tests { "bytesPrefixHex": "0102", }), ); - let first = crate::EventMaterializer::materialize(&materializer, &observation); - let second = crate::EventMaterializer::materialize(&materializer, &observation); + let first = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + let second = crate::MtApiEventMaterializer::materialize(&materializer, &observation); let first_json = match serde_json::to_string(&first) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { diff --git a/kb-lib/src/materializer/compliance/constants.rs b/kb-lib/src/materializer/compliance/constants.rs index e47bbc8..21a5c9b 100644 --- a/kb-lib/src/materializer/compliance/constants.rs +++ b/kb-lib/src/materializer/compliance/constants.rs @@ -4,4 +4,4 @@ //! Local constants for the native compliance audit materializer. /// Canonical tracing target for this component. -pub(crate) const TRACING_TARGET: &str = "kb-lib.materializer.compliance"; +pub(crate) const MT_COMPLIANCE_AUDIT_TRACING_TARGET: &str = "kb-lib.materializer.compliance"; diff --git a/kb-lib/src/materializer/fees.rs b/kb-lib/src/materializer/fees.rs index 0fd4295..80f3fca 100644 --- a/kb-lib/src/materializer/fees.rs +++ b/kb-lib/src/materializer/fees.rs @@ -1,6 +1,11 @@ // file: kb-lib/src/materializer/fees.rs -// version: 1 +// version: 2 //! `fees` materializer family. -pub mod core; +mod core; + +/// Fee materializer for committed Token-2022 fee observations. +pub use self::core::MtFeesMaterializer; +/// Materializes authoritative Token-2022 fee extension snapshots. +pub use self::core::materialize_token2022_fee_state_snapshots; diff --git a/kb-lib/src/materializer/fees/core.rs b/kb-lib/src/materializer/fees/core.rs index e5cb3db..7041a3d 100644 --- a/kb-lib/src/materializer/fees/core.rs +++ b/kb-lib/src/materializer/fees/core.rs @@ -1,10 +1,432 @@ // file: kb-lib/src/materializer/fees/core.rs -// version: 1 +// version: 2 -//! Migration boundary for legacy crate `kb_materializer_fees`. +//! Stable fee projections derived from exact committed Token-2022 observations. -/// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_fees"; +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[crate::MdEventFamily::Fee]; +const SPL_TOKEN2022_SURFACE: &str = "spl_token2022"; +const TOKEN2022_FEE_ENTRIES: &[&str] = &[ + "initialize_transfer_fee_config", + "set_transfer_fee", + "withdraw_withheld_tokens_from_mint", + "withdraw_withheld_tokens_from_accounts", + "harvest_withheld_tokens_to_mint", + "transfer_checked_with_fee", + "initialize_confidential_transfer_fee_config", + "withdraw_confidential_withheld_tokens_from_mint", + "withdraw_confidential_withheld_tokens_from_accounts", + "harvest_confidential_withheld_tokens_to_mint", + "enable_confidential_harvest_to_mint", + "disable_confidential_harvest_to_mint", + "transfer_confidential_tokens_with_fee", +]; -/// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +/// Fee materializer for committed Token-2022 fee instructions. +#[derive(Clone, Debug, Default)] +pub struct MtFeesMaterializer; + +impl crate::MtMaterializer for crate::MtFeesMaterializer { + fn materializer_name(&self) -> &'static str { + return "kb_materializer_fees"; + } + fn materializer_version(&self) -> &'static str { + return env!("CARGO_PKG_VERSION"); + } + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { + return accepts_event(event); + } + fn materialize_event( + &self, + _event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + return std::result::Result::Ok(std::vec::Vec::new()); + } +} + +impl crate::MtApiEventMaterializer for crate::MtFeesMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { + name: "fees".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + }; + } + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { + return ACCEPTED_FAMILIES; + } + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { + return accepts_event(&observation.event); + } + fn transaction_policy( + &self, + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; + } + fn materialize( + &self, + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { + if !accepts_event(&observation.event) { + return crate::MtApiMaterializerExecutionResult::ignored(); + } + if observation.transaction_failed || !observation.observation_committed { + return crate::MtApiMaterializerExecutionResult::refused( + "failed_transaction_fee_refused", + "failed or uncommitted Token-2022 observations cannot create fee outputs", + ); + } + let operation = observation.event.event_name.0.clone(); + let accounts = observation + .payload_json + .get("accounts") + .cloned() + .unwrap_or(serde_json::Value::Null); + let parameters = observation + .payload_json + .get("parameters") + .cloned() + .unwrap_or_else(|| return observation.payload_json.clone()); + let output = crate::MtApiMaterializedOutput { + output_key: format!("token2022_fee:{operation}:0"), + family: crate::MdMaterializedEventFamily::Fee, + payload_json: serde_json::json!({ + "projectionVersion": 1, + "projectionSemantics": "committed_instruction_fee_event", + "domain": fee_domain(observation.event.event_name.0.as_str()), + "operation": operation, + "programId": observation.event.program_id.0.clone(), + "signature": observation.event.signature.0.clone(), + "slot": observation.event.slot.0, + "instructionPath": observation.event.instruction_path.0.clone(), + "transactionSucceeded": true, + "accounts": accounts, + "parameters": parameters, + "stateReadRequired": state_read_required( + observation.event.event_name.0.as_str(), + ), + "confidentialValuesDecrypted": false, + }), + }; + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, + outputs: std::vec![output], + diagnostics: std::vec::Vec::new(), + }; + } +} + +fn accepts_event(event: &crate::MdDecodedProtocolEvent) -> bool { + return event.event_family == crate::MdEventFamily::Fee + && event.surface_code.0 == SPL_TOKEN2022_SURFACE + && event.program_id.0 == kb_program_ids::SPL_TOKEN2022_PROGRAM_ID + && contains(TOKEN2022_FEE_ENTRIES, event.event_name.0.as_str()); +} + +fn fee_domain(operation: &str) -> &'static str { + if operation.contains("confidential") { + return "token2022_confidential_transfer_fee"; + } + return "token2022_transfer_fee"; +} + +fn state_read_required(operation: &str) -> bool { + return matches!( + operation, + "initialize_transfer_fee_config" + | "set_transfer_fee" + | "withdraw_withheld_tokens_from_mint" + | "withdraw_withheld_tokens_from_accounts" + | "harvest_withheld_tokens_to_mint" + | "initialize_confidential_transfer_fee_config" + | "withdraw_confidential_withheld_tokens_from_mint" + | "withdraw_confidential_withheld_tokens_from_accounts" + | "harvest_confidential_withheld_tokens_to_mint" + | "enable_confidential_harvest_to_mint" + | "disable_confidential_harvest_to_mint" + ); +} + +fn contains(entries: &[&str], entry_code: &str) -> bool { + return entries.iter().any(|entry| return *entry == entry_code); +} + +/// Materialize authoritative Token-2022 fee extension snapshots without decrypting confidential values. +pub fn materialize_token2022_fee_state_snapshots( + account_key: &str, + slot: u64, + state: &crate::DcToken2022State, +) -> std::result::Result, String> { + if account_key.is_empty() { + return std::result::Result::Err( + "Token-2022 fee state snapshot requires a non-empty account key".to_string(), + ); + } + let state_kind = match state.kind { + crate::DcToken2022StateKind::Mint => "mint", + crate::DcToken2022StateKind::Account => "account", + crate::DcToken2022StateKind::Multisig => { + return std::result::Result::Err( + "Token-2022 multisig state cannot contain fee extensions".to_string(), + ); + }, + }; + let mut outputs = std::vec::Vec::new(); + for entry in &state.extensions { + let confidential = match entry.extension_name { + "transfer_fee_config" | "transfer_fee_amount" => false, + "confidential_transfer_fee_config" | "confidential_transfer_fee_amount" => true, + _ => continue, + }; + let expected_kind = match entry.extension_name { + "transfer_fee_config" | "confidential_transfer_fee_config" => "mint", + "transfer_fee_amount" | "confidential_transfer_fee_amount" => "account", + _ => continue, + }; + if state_kind != expected_kind { + return std::result::Result::Err(format!( + "Token-2022 {} extension requires {expected_kind} state, got {state_kind}", + entry.extension_name + )); + } + outputs.push(crate::MtApiMaterializedOutput { + output_key: format!( + "token2022_fee_state:{}:{account_key}:{slot}", + entry.extension_name + ), + family: crate::MdMaterializedEventFamily::Fee, + payload_json: serde_json::json!({ + "projectionVersion": 1, + "projectionSemantics": "authoritative_bounded_fee_state_snapshot", + "domain": if confidential { + "token2022_confidential_transfer_fee_state" + } else { + "token2022_transfer_fee_state" + }, + "idempotenceKey": format!( + "token2022_fee_state:{}:{account_key}:{slot}", + entry.extension_name + ), + "accountKey": account_key, + "slot": slot, + "programId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "stateKind": state_kind, + "extensionType": entry.extension_type, + "extensionName": entry.extension_name, + "valueHex": entry.value_hex, + "valueFields": entry.value_fields, + "containsConfidentialState": confidential, + "confidentialValuesDecrypted": false, + "finalAccountStateCaptured": true, + "provenance": { + "processorName": "fees", + "processorVersion": env!("CARGO_PKG_VERSION"), + "source": "bounded_token2022_state_parser" + } + }), + }); + } + return std::result::Result::Ok(outputs); +} + +#[cfg(test)] +mod tests { + fn observation( + surface_code: &str, + program_id: &str, + entry_code: &str, + transaction_failed: bool, + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { + event_key: format!("{entry_code}:0"), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId(program_id.to_string()), + protocol_code: crate::MdProtocolCode("spl_token2022".to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")), + event_name: crate::MdEventName(entry_code.to_string()), + event_family: crate::MdEventFamily::Fee, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, + }, + payload_json: serde_json::json!({ + "accounts": [{"position": 0, "role": "mint", "accountKey": "mint111"}], + "parameters": {"extension": "transfer_fee", "basisPoints": 25}, + }), + transaction_failed, + transaction_error: if transaction_failed { + std::option::Option::Some(serde_json::json!({"InstructionError": [0, "Custom"]})) + } else { + std::option::Option::None + }, + observation_committed: !transaction_failed, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, + evidence: std::vec!["fixture".to_string()], + }, + }; + } + + #[test] + fn committed_token2022_fee_instruction_creates_one_stable_output() { + let observation = observation( + super::SPL_TOKEN2022_SURFACE, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "set_transfer_fee", + false, + ); + let result = + crate::MtApiEventMaterializer::materialize(&crate::MtFeesMaterializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs.len(), 1); + assert_eq!(result.outputs[0].family, crate::MdMaterializedEventFamily::Fee); + assert_eq!(result.outputs[0].output_key, "token2022_fee:set_transfer_fee:0"); + assert_eq!(result.outputs[0].payload_json["stateReadRequired"], true); + } + + #[test] + fn failed_token2022_fee_instruction_is_refused() { + let observation = observation( + super::SPL_TOKEN2022_SURFACE, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "harvest_withheld_tokens_to_mint", + true, + ); + let result = + crate::MtApiEventMaterializer::materialize(&crate::MtFeesMaterializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); + assert!(result.outputs.is_empty()); + } + + #[test] + fn classic_token_and_program_surface_mismatches_are_ignored() { + let classic = observation( + "spl_token", + kb_program_ids::SPL_TOKEN_PROGRAM_ID, + "set_transfer_fee", + false, + ); + let wrong_program = observation( + super::SPL_TOKEN2022_SURFACE, + kb_program_ids::SPL_TOKEN_PROGRAM_ID, + "set_transfer_fee", + false, + ); + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &crate::MtFeesMaterializer, + &classic, + )); + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &crate::MtFeesMaterializer, + &wrong_program, + )); + } + + #[test] + fn transfer_checked_with_fee_is_self_contained_but_state_mutations_are_not() { + assert!(!super::state_read_required("transfer_checked_with_fee")); + assert!(super::state_read_required("withdraw_withheld_tokens_from_accounts")); + } + + #[test] + fn committed_confidential_fee_instruction_is_projected_without_decryption() { + let observation = observation( + super::SPL_TOKEN2022_SURFACE, + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "initialize_confidential_transfer_fee_config", + false, + ); + let result = + crate::MtApiEventMaterializer::materialize(&crate::MtFeesMaterializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs.len(), 1); + assert_eq!(result.outputs[0].payload_json["domain"], "token2022_confidential_transfer_fee"); + assert_eq!(result.outputs[0].payload_json["stateReadRequired"], true); + assert_eq!(result.outputs[0].payload_json["confidentialValuesDecrypted"], false); + } + + #[test] + fn confidential_transfer_with_fee_is_instructionally_self_contained() { + assert!(!super::state_read_required("transfer_confidential_tokens_with_fee",)); + assert_eq!( + super::fee_domain("transfer_confidential_tokens_with_fee"), + "token2022_confidential_transfer_fee" + ); + } + + #[test] + fn public_fee_state_snapshots_are_owned_once_and_idempotent() { + let mint = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Mint, + base_fields: serde_json::json!({}), + base_hex: "00".to_string(), + account_type: std::option::Option::Some(1), + extensions: std::vec![crate::DcToken2022TlvEntry { + extension_type: 1, + extension_name: "transfer_fee_config", + value_hex: "01".to_string(), + value_fields: serde_json::json!({"withheldAmount":"7"}), + }], + }; + let first = crate::materialize_token2022_fee_state_snapshots("mint111", 42, &mint); + let second = crate::materialize_token2022_fee_state_snapshots("mint111", 42, &mint); + assert!(first.is_ok()); + assert_eq!(first, second); + let outputs = match first { + std::result::Result::Ok(outputs) => outputs, + std::result::Result::Err(error) => panic!("unexpected error: {error}"), + }; + assert_eq!(outputs.len(), 1); + assert_eq!(outputs[0].payload_json["stateKind"], "mint"); + assert_eq!(outputs[0].payload_json["valueFields"]["withheldAmount"], "7"); + assert_eq!(outputs[0].payload_json["confidentialValuesDecrypted"], false); + } + + #[test] + fn confidential_fee_amount_preserves_ciphertext_without_decryption_claim() { + let account = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Account, + base_fields: serde_json::json!({}), + base_hex: "00".to_string(), + account_type: std::option::Option::Some(2), + extensions: std::vec![crate::DcToken2022TlvEntry { + extension_type: 17, + extension_name: "confidential_transfer_fee_amount", + value_hex: "02".to_string(), + value_fields: serde_json::json!({"withheldAmount":"ciphertext"}), + }], + }; + let result = crate::materialize_token2022_fee_state_snapshots("account111", 43, &account); + assert!(result.is_ok()); + let outputs = match result { + std::result::Result::Ok(outputs) => outputs, + std::result::Result::Err(error) => panic!("unexpected error: {error}"), + }; + assert_eq!(outputs[0].payload_json["containsConfidentialState"], true); + assert_eq!(outputs[0].payload_json["confidentialValuesDecrypted"], false); + assert_eq!(outputs[0].payload_json["valueFields"]["withheldAmount"], "ciphertext"); + } + + #[test] + fn fee_state_snapshot_rejects_wrong_state_kind_and_empty_identity() { + let wrong = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Account, + base_fields: serde_json::json!({}), + base_hex: "00".to_string(), + account_type: std::option::Option::Some(2), + extensions: std::vec![crate::DcToken2022TlvEntry { + extension_type: 1, + extension_name: "transfer_fee_config", + value_hex: "01".to_string(), + value_fields: serde_json::json!({}), + }], + }; + assert!( + crate::materialize_token2022_fee_state_snapshots("account111", 44, &wrong,).is_err() + ); + assert!(crate::materialize_token2022_fee_state_snapshots("", 44, &wrong,).is_err()); + } +} diff --git a/kb-lib/src/materializer/governance.rs b/kb-lib/src/materializer/governance.rs index fafad37..d586494 100644 --- a/kb-lib/src/materializer/governance.rs +++ b/kb-lib/src/materializer/governance.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/governance.rs -// version: 1 +// version: 2 //! `governance` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/governance/core.rs b/kb-lib/src/materializer/governance/core.rs index 35736bd..e1f5591 100644 --- a/kb-lib/src/materializer/governance/core.rs +++ b/kb-lib/src/materializer/governance/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/governance/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_governance`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_governance"; +const LEGACY_CRATE: &str = "kb_materializer_governance"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/lending.rs b/kb-lib/src/materializer/lending.rs index efee829..7c00cdc 100644 --- a/kb-lib/src/materializer/lending.rs +++ b/kb-lib/src/materializer/lending.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/lending.rs -// version: 1 +// version: 2 //! `lending` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/lending/core.rs b/kb-lib/src/materializer/lending/core.rs index b481d6e..9741c17 100644 --- a/kb-lib/src/materializer/lending/core.rs +++ b/kb-lib/src/materializer/lending/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/lending/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_lending`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_lending"; +const LEGACY_CRATE: &str = "kb_materializer_lending"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/lifecycle.rs b/kb-lib/src/materializer/lifecycle.rs index 6158d65..6408034 100644 --- a/kb-lib/src/materializer/lifecycle.rs +++ b/kb-lib/src/materializer/lifecycle.rs @@ -1,12 +1,13 @@ // file: kb-lib/src/materializer/lifecycle.rs -// version: 2 +// version: 3 //! `lifecycle` materializer family. mod constants; -pub mod core; +mod core; -pub(crate) use crate::materializer::lifecycle::constants::TRACING_TARGET as MATERIALIZER_LIFECYCLE_TRACING_TARGET; +/// Canonical tracing target for the native lifecycle materializer. +pub(crate) use self::constants::MT_LIFECYCLE_TRACING_TARGET; /// Stable native lifecycle materializer. -pub use crate::materializer::lifecycle::core::LifecycleMaterializer; +pub use self::core::MtLifecycleMaterializer; diff --git a/kb-lib/src/materializer/lifecycle/constants.rs b/kb-lib/src/materializer/lifecycle/constants.rs index a5c1215..f4e63d0 100644 --- a/kb-lib/src/materializer/lifecycle/constants.rs +++ b/kb-lib/src/materializer/lifecycle/constants.rs @@ -4,4 +4,4 @@ //! Local constants for the native lifecycle materializer. /// Canonical tracing target for this component. -pub(crate) const TRACING_TARGET: &str = "kb-lib.materializer.lifecycle"; +pub(crate) const MT_LIFECYCLE_TRACING_TARGET: &str = "kb-lib.materializer.lifecycle"; diff --git a/kb-lib/src/materializer/lifecycle/core.rs b/kb-lib/src/materializer/lifecycle/core.rs index aea7f85..1fca2a8 100644 --- a/kb-lib/src/materializer/lifecycle/core.rs +++ b/kb-lib/src/materializer/lifecycle/core.rs @@ -3,10 +3,10 @@ //! Stable lifecycle projections derived from exact decoded observations. -const ACCEPTED_FAMILIES: &[crate::EventFamily] = &[ - crate::EventFamily::Lifecycle, - crate::EventFamily::Admin, - crate::EventFamily::Audit, +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[ + crate::MdEventFamily::Lifecycle, + crate::MdEventFamily::Admin, + crate::MdEventFamily::Audit, ]; const ADDRESS_LOOKUP_TABLE_SURFACE: &str = "solana_native_address_lookup_table"; const ADDRESS_LOOKUP_TABLE_ENTRIES: &[&str] = &[ @@ -121,9 +121,9 @@ impl ProjectionKind { /// Stable lifecycle materializer for supported native lifecycle projections. #[derive(Clone, Debug, Default)] -pub struct LifecycleMaterializer; +pub struct MtLifecycleMaterializer; -impl crate::Materializer for crate::LifecycleMaterializer { +impl crate::MtMaterializer for crate::MtLifecycleMaterializer { fn materializer_name(&self) -> &'static str { return "kb_materializer_lifecycle"; } @@ -132,7 +132,7 @@ impl crate::Materializer for crate::LifecycleMaterializer { return env!("CARGO_PKG_VERSION"); } - fn accepts_event(&self, event: &crate::DecodedProtocolEvent) -> bool { + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { return family_is_accepted(event.event_family) && static_projection(event.surface_code.0.as_str(), event.event_name.0.as_str()) .is_some(); @@ -140,60 +140,60 @@ impl crate::Materializer for crate::LifecycleMaterializer { fn materialize_event( &self, - event: &crate::DecodedProtocolEvent, - ) -> kb_core::Result> { - if !crate::Materializer::accepts_event(self, event) { + event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + if !crate::MtMaterializer::accepts_event(self, event) { return std::result::Result::Ok(std::vec::Vec::new()); } return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::EventMaterializer for crate::LifecycleMaterializer { - fn identity(&self) -> crate::MaterializerIdentity { - return crate::MaterializerIdentity { +impl crate::MtApiEventMaterializer for crate::MtLifecycleMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { name: "solana_native_lifecycle".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn accepted_families(&self) -> &'static [crate::EventFamily] { + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { return ACCEPTED_FAMILIES; } - fn accepts_observation(&self, observation: &crate::DecodedObservation) -> bool { + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { return family_is_accepted(observation.event.event_family) && observation_projection(observation).is_some(); } fn transaction_policy( &self, - _family: crate::EventFamily, - ) -> crate::MaterializationTransactionPolicy { - return crate::MaterializationTransactionPolicy::SuccessfulCommittedOnly; + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; } fn materialize( &self, - observation: &crate::DecodedObservation, - ) -> crate::MaterializerExecutionResult { + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { let projection = match observation_projection(observation) { std::option::Option::Some(value) => value, std::option::Option::None => { tracing::debug!( - target: crate::MATERIALIZER_LIFECYCLE_TRACING_TARGET, + target: crate::MT_LIFECYCLE_TRACING_TARGET, action = "materialize_lifecycle", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), accepted = false, "ignore observation outside supported native lifecycle projections" ); - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); }, }; if observation.transaction_failed || !observation.observation_committed { tracing::debug!( - target: crate::MATERIALIZER_LIFECYCLE_TRACING_TARGET, + target: crate::MT_LIFECYCLE_TRACING_TARGET, action = "materialize_lifecycle", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -202,7 +202,7 @@ impl crate::EventMaterializer for crate::LifecycleMaterializer { transaction_failed = observation.transaction_failed, "refuse uncommitted native lifecycle observation" ); - return crate::MaterializerExecutionResult::refused( + return crate::MtApiMaterializerExecutionResult::refused( "failed_transaction_lifecycle_refused", "failed or uncommitted native lifecycle observations cannot create lifecycle outputs", ); @@ -225,7 +225,7 @@ impl crate::EventMaterializer for crate::LifecycleMaterializer { let projection_details = projection_details(projection, &accounts, ¶meters, operation.as_str()); tracing::debug!( - target: crate::MATERIALIZER_LIFECYCLE_TRACING_TARGET, + target: crate::MT_LIFECYCLE_TRACING_TARGET, action = "materialize_lifecycle", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -235,9 +235,9 @@ impl crate::EventMaterializer for crate::LifecycleMaterializer { output_count = 1_usize, "materialize committed native lifecycle observation" ); - let output = crate::MaterializedOutput { + let output = crate::MtApiMaterializedOutput { output_key, - family: crate::MaterializedEventFamily::Lifecycle, + family: crate::MdMaterializedEventFamily::Lifecycle, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "committed_instruction_lifecycle_event", @@ -254,20 +254,20 @@ impl crate::EventMaterializer for crate::LifecycleMaterializer { "projection": projection_details, }), }; - return crate::MaterializerExecutionResult { - status: crate::MaterializerOutcomeStatus::Inserted, + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, outputs: std::vec![output], diagnostics: std::vec::Vec::new(), }; } } -fn family_is_accepted(family: crate::EventFamily) -> bool { +fn family_is_accepted(family: crate::MdEventFamily) -> bool { return ACCEPTED_FAMILIES.iter().any(|accepted| return *accepted == family); } fn observation_projection( - observation: &crate::DecodedObservation, + observation: &crate::DcApiDecodedObservation, ) -> std::option::Option { let surface_code = observation.event.surface_code.0.as_str(); let entry_code = observation.event.event_name.0.as_str(); @@ -479,25 +479,25 @@ mod tests { fn observation_with_payload( surface_code: &str, entry_code: &str, - event_family: crate::EventFamily, + event_family: crate::MdEventFamily, transaction_failed: bool, accounts: serde_json::Value, parameters: serde_json::Value, - ) -> crate::DecodedObservation { - return crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { event_key: format!("{entry_code}:0"), - event: crate::DecodedProtocolEvent { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(42), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId("program-id".to_string()), - protocol_code: crate::ProtocolCode("solana_native".to_string()), - surface_code: crate::SurfaceCode(surface_code.to_string()), - event_code: crate::EventCode(format!("{surface_code}.{entry_code}")), - event_name: crate::EventName(entry_code.to_string()), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId("program-id".to_string()), + protocol_code: crate::MdProtocolCode("solana_native".to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")), + event_name: crate::MdEventName(entry_code.to_string()), event_family, - source_kind: crate::EventSourceKind::Instruction, - confidence: crate::DecoderConfidence::ManualExact, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, }, payload_json: serde_json::json!({ "accounts": accounts, @@ -510,9 +510,9 @@ mod tests { std::option::Option::None }, observation_committed: !transaction_failed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec!["fixture".to_string()], }, }; @@ -522,11 +522,11 @@ mod tests { surface_code: &str, entry_code: &str, transaction_failed: bool, - ) -> crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { return observation_with_payload( surface_code, entry_code, - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, transaction_failed, serde_json::json!([{"role": "target", "accountKey": "account"}]), serde_json::json!({"value": 41}), @@ -535,9 +535,9 @@ mod tests { fn nonce_observation( entry_code: &str, - family: crate::EventFamily, + family: crate::MdEventFamily, transaction_failed: bool, - ) -> crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { return observation_with_payload( super::SYSTEM_SURFACE, entry_code, @@ -558,10 +558,10 @@ mod tests { fn slashing_observation( entry_code: &str, transaction_failed: bool, - ) -> crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { let (family, accounts) = if entry_code == "duplicate_block_proof" { ( - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, serde_json::json!([ {"role": "proof_account", "accountKey": "proof111"}, {"role": "violation_report", "accountKey": "report111"}, @@ -571,7 +571,7 @@ mod tests { ) } else { ( - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, serde_json::json!([ {"role": "violation_report", "accountKey": "report111"}, {"role": "destination", "accountKey": "destination111"} @@ -599,7 +599,7 @@ mod tests { entry_code: &str, context_state_requested: bool, transaction_failed: bool, - ) -> crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { let accounts = if entry_code == "close_context_state" { serde_json::json!([ {"role": "proof_context_state", "accountKey": "context111"}, @@ -615,9 +615,9 @@ mod tests { serde_json::json!([]) }; let family = if entry_code == "close_context_state" { - crate::EventFamily::Lifecycle + crate::MdEventFamily::Lifecycle } else { - crate::EventFamily::Audit + crate::MdEventFamily::Audit }; return observation_with_payload( super::ZK_ELGAMAL_PROOF_SURFACE, @@ -634,12 +634,12 @@ mod tests { #[test] fn successful_alt_lifecycle_creates_one_stable_output() { - let materializer = crate::LifecycleMaterializer; - let result = crate::EventMaterializer::materialize( + let materializer = crate::MtLifecycleMaterializer; + let result = crate::MtApiEventMaterializer::materialize( &materializer, &observation(super::ADDRESS_LOOKUP_TABLE_SURFACE, "create_lookup_table", false), ); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs.len(), 1); assert_eq!(result.outputs[0].output_key, "address_lookup_table:create_lookup_table:0"); assert_eq!(result.outputs[0].payload_json["domain"], "address_lookup_table"); @@ -648,12 +648,12 @@ mod tests { #[test] fn successful_loader_lifecycle_creates_program_projection() { - let materializer = crate::LifecycleMaterializer; - let result = crate::EventMaterializer::materialize( + let materializer = crate::MtLifecycleMaterializer; + let result = crate::MtApiEventMaterializer::materialize( &materializer, &observation(super::BPF_LOADER_UPGRADEABLE_SURFACE, "deploy_with_max_data_len", false), ); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!( result.outputs[0].output_key, "program_loader:solana_native_bpf_loader_upgradeable:deploy_with_max_data_len:0" @@ -667,19 +667,19 @@ mod tests { #[test] fn successful_feature_revoke_creates_feature_gate_projection() { - let materializer = crate::LifecycleMaterializer; - let result = crate::EventMaterializer::materialize( + let materializer = crate::MtLifecycleMaterializer; + let result = crate::MtApiEventMaterializer::materialize( &materializer, &observation(super::FEATURE_SURFACE, "revoke_pending_activation", false), ); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].output_key, "feature_gate:revoke_pending_activation:0"); assert_eq!(result.outputs[0].payload_json["domain"], "feature_gate"); } #[test] fn every_committed_system_account_operation_creates_a_lifecycle_projection() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; for (operation, role, transition) in [ ("create_account", "new_account", "created_allocated_funded_and_assigned"), ( @@ -698,7 +698,7 @@ mod tests { let observation = observation_with_payload( super::SYSTEM_SURFACE, operation, - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, serde_json::json!([ {"role": role, "accountKey": "target111"}, @@ -712,8 +712,8 @@ mod tests { "seed": "seed", }), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].output_key, format!("system_account:{operation}:0")); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "target111"); assert_eq!(result.outputs[0].payload_json["projection"]["stateTransition"], transition); @@ -722,11 +722,11 @@ mod tests { #[test] fn system_account_creation_does_not_duplicate_balance_changes() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observation = observation_with_payload( super::SYSTEM_SURFACE, "create_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, serde_json::json!([ {"role": "funding_account", "accountKey": "funding111"}, @@ -734,7 +734,7 @@ mod tests { ]), serde_json::json!({"lamports": 55, "space": 64, "owner": "owner111"}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); assert_eq!(result.outputs[0].payload_json["projection"]["requestedLamports"], 55); assert_eq!( result.outputs[0].payload_json["projection"]["lamportTransferRepresentedByCoreBalanceChanges"], @@ -745,26 +745,29 @@ mod tests { #[test] fn every_committed_system_nonce_operation_creates_a_lifecycle_projection() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; for (entry_code, family, transition) in [ - ("initialize_nonce_account", crate::EventFamily::Lifecycle, "initialized"), - ("advance_nonce_account", crate::EventFamily::Lifecycle, "nonce_advanced"), - ("authorize_nonce_account", crate::EventFamily::Admin, "authority_changed"), + ("initialize_nonce_account", crate::MdEventFamily::Lifecycle, "initialized"), + ("advance_nonce_account", crate::MdEventFamily::Lifecycle, "nonce_advanced"), + ("authorize_nonce_account", crate::MdEventFamily::Admin, "authority_changed"), ( "upgrade_nonce_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, "legacy_version_upgraded", ), ( "withdraw_nonce_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, "lamports_withdrawn_possible_closure", ), ] { let observation = nonce_observation(entry_code, family, false); - assert!(crate::EventMaterializer::accepts_observation(&materializer, &observation,)); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + assert!(crate::MtApiEventMaterializer::accepts_observation( + &materializer, + &observation, + )); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].payload_json["domain"], "durable_nonce_account"); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "nonce111"); assert_eq!( @@ -777,10 +780,10 @@ mod tests { #[test] fn nonce_withdrawal_preserves_conditional_closure_semantics() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observation = - nonce_observation("withdraw_nonce_account", crate::EventFamily::Lifecycle, false); - let result = crate::EventMaterializer::materialize(&materializer, &observation); + nonce_observation("withdraw_nonce_account", crate::MdEventFamily::Lifecycle, false); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); assert_eq!(result.outputs[0].payload_json["projection"]["withdrawLamports"], 55); assert_eq!( result.outputs[0].payload_json["projection"]["lamportDestination"], @@ -799,13 +802,16 @@ mod tests { #[test] fn zk_context_is_materialized_only_when_requested() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let without_context = zk_observation("verify_zero_ciphertext", false, false); - assert!(!crate::EventMaterializer::accepts_observation(&materializer, &without_context,)); + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &materializer, + &without_context, + )); let with_context = zk_observation("verify_zero_ciphertext", true, false); - assert!(crate::EventMaterializer::accepts_observation(&materializer, &with_context,)); - let result = crate::EventMaterializer::materialize(&materializer, &with_context); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + assert!(crate::MtApiEventMaterializer::accepts_observation(&materializer, &with_context,)); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &with_context); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].payload_json["domain"], "zk_proof_context"); assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "context111"); assert_eq!( @@ -820,10 +826,10 @@ mod tests { #[test] fn zk_context_close_creates_a_stable_lifecycle_projection() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observation = zk_observation("close_context_state", false, false); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs[0].output_key, "zk_proof_context:close_context_state:0"); assert_eq!( result.outputs[0].payload_json["projection"]["lamportDestination"], @@ -837,11 +843,11 @@ mod tests { #[test] fn successful_slashing_proof_initializes_violation_report_projection() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observation = slashing_observation("duplicate_block_proof", false); - assert!(crate::EventMaterializer::accepts_observation(&materializer, &observation,)); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + assert!(crate::MtApiEventMaterializer::accepts_observation(&materializer, &observation,)); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!( result.outputs[0].output_key, "slashing_violation_report:duplicate_block_proof:0" @@ -854,10 +860,10 @@ mod tests { #[test] fn successful_slashing_close_creates_stable_closure_projection() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observation = slashing_observation("close_violation_report", false); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!( result.outputs[0].payload_json["projection"]["stateTransition"], "closed_after_minimum_retention_lamports_reclaimed_owner_reset_to_system_program" @@ -871,78 +877,86 @@ mod tests { #[test] fn historical_zk_token_proof_is_not_materialized() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observation = observation_with_payload( "solana_native_zk_token_proof", "close_context_state", - crate::EventFamily::Audit, + crate::MdEventFamily::Audit, false, serde_json::json!([]), serde_json::json!({}), ); - assert!(!crate::EventMaterializer::accepts_observation(&materializer, &observation,)); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Ignored); + assert!(!crate::MtApiEventMaterializer::accepts_observation(&materializer, &observation,)); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); } #[test] fn loader_write_and_admin_events_are_not_lifecycle_projections() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; for entry_code in ["write", "set_authority", "transfer_authority"] { let observation = observation(super::BPF_LOADER_UPGRADEABLE_SURFACE, entry_code, false); - assert!(!crate::EventMaterializer::accepts_observation(&materializer, &observation,)); + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &materializer, + &observation, + )); } } #[test] fn unrelated_lifecycle_is_ignored() { - let materializer = crate::LifecycleMaterializer; - let result = crate::EventMaterializer::materialize( + let materializer = crate::MtLifecycleMaterializer; + let result = crate::MtApiEventMaterializer::materialize( &materializer, &observation(super::SYSTEM_SURFACE, "transfer", false), ); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Ignored); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); } #[test] fn ata_lifecycle_is_owned_by_token_accounts_materializer_only() { let mut observation = observation("spl_associated_token_account", "create", false); observation.event.program_id = - crate::ProgramId(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string()); - assert!(!crate::EventMaterializer::accepts_observation( - &crate::LifecycleMaterializer, + crate::MdProgramId(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string()); + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &crate::MtLifecycleMaterializer, &observation, )); - let result = - crate::EventMaterializer::materialize(&crate::LifecycleMaterializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Ignored); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtLifecycleMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); assert!(result.outputs.is_empty()); } #[test] fn failed_native_lifecycle_is_refused() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observations = [ observation(super::ADDRESS_LOOKUP_TABLE_SURFACE, "close_lookup_table", true), observation(super::LOADER_V4_SURFACE, "deploy", true), - nonce_observation("authorize_nonce_account", crate::EventFamily::Admin, true), + nonce_observation("authorize_nonce_account", crate::MdEventFamily::Admin, true), zk_observation("verify_zero_ciphertext", true, true), slashing_observation("duplicate_block_proof", true), ]; for observation in observations { - let policy = crate::validate_materialization_policy(&materializer, &observation); + let policy = crate::materializer_api_validate_materialization_policy( + &materializer, + &observation, + ); assert!(policy.is_err()); - let direct = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(direct.status, crate::MaterializerOutcomeStatus::Refused); + let direct = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(direct.status, crate::MtApiMaterializerOutcomeStatus::Refused); } } #[test] fn output_serialization_is_deterministic() { - let materializer = crate::LifecycleMaterializer; + let materializer = crate::MtLifecycleMaterializer; let observation = zk_observation("verify_batched_range_proof_u64", true, false); - let first = crate::EventMaterializer::materialize(&materializer, &observation); - let second = crate::EventMaterializer::materialize(&materializer, &observation); + let first = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + let second = crate::MtApiEventMaterializer::materialize(&materializer, &observation); let first_json = match serde_json::to_string(&first) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => { diff --git a/kb-lib/src/materializer/liquidity.rs b/kb-lib/src/materializer/liquidity.rs index 69479b5..38e5801 100644 --- a/kb-lib/src/materializer/liquidity.rs +++ b/kb-lib/src/materializer/liquidity.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/liquidity.rs -// version: 1 +// version: 2 //! `liquidity` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/liquidity/core.rs b/kb-lib/src/materializer/liquidity/core.rs index 03ec80a..dbfb075 100644 --- a/kb-lib/src/materializer/liquidity/core.rs +++ b/kb-lib/src/materializer/liquidity/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/liquidity/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_liquidity`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_liquidity"; +const LEGACY_CRATE: &str = "kb_materializer_liquidity"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/metadata.rs b/kb-lib/src/materializer/metadata.rs index 58d7ba9..e916720 100644 --- a/kb-lib/src/materializer/metadata.rs +++ b/kb-lib/src/materializer/metadata.rs @@ -1,6 +1,15 @@ // file: kb-lib/src/materializer/metadata.rs -// version: 1 +// version: 2 //! `metadata` materializer family. -pub mod core; +mod core; + +/// Token-2022 and Metaplex metadata snapshot materializer. +pub use self::core::MtMetadataMaterializer; +/// Materializes one canonical non-Metadata Metaplex account snapshot. +pub use self::core::materialize_metaplex_account_snapshot; +/// Materializes one canonical Metaplex Metadata account snapshot. +pub use self::core::materialize_metaplex_metadata_snapshot; +/// Materializes Token-2022 embedded metadata and group snapshots. +pub use self::core::materialize_token2022_metadata_snapshot; diff --git a/kb-lib/src/materializer/metadata/core.rs b/kb-lib/src/materializer/metadata/core.rs index ea64b17..4a983dd 100644 --- a/kb-lib/src/materializer/metadata/core.rs +++ b/kb-lib/src/materializer/metadata/core.rs @@ -1,10 +1,565 @@ // file: kb-lib/src/materializer/metadata/core.rs -// version: 1 +// version: 2 -//! Migration boundary for legacy crate `kb_materializer_metadata`. +//! Stable Token-2022 and Metaplex metadata snapshot materializer. -/// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_metadata"; +/// Initial materializer implementation placeholder. +#[derive(Clone, Debug, Default)] +pub struct MtMetadataMaterializer; -/// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +impl crate::MtMaterializer for crate::MtMetadataMaterializer { + fn materializer_name(&self) -> &'static str { + return "kb_materializer_metadata"; + } + + fn materializer_version(&self) -> &'static str { + return env!("CARGO_PKG_VERSION"); + } + + fn accepts_event(&self, _event: &crate::MdDecodedProtocolEvent) -> bool { + return false; + } + + fn materialize_event( + &self, + event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + let materialized = crate::MdMaterializedEvent { + signature: event.signature.clone(), + slot: event.slot, + decoded_family: event.event_family, + materialized_family: crate::MdMaterializedEventFamily::Metadata, + }; + return std::result::Result::Ok(std::vec![materialized]); + } +} + +/// Materialize embedded Token-2022 metadata, group, and group-member extensions. +pub fn materialize_token2022_metadata_snapshot( + account_key: &str, + slot: u64, + state: &crate::DcToken2022State, +) -> std::result::Result, String> { + if account_key.is_empty() { + return std::result::Result::Err( + "Token-2022 metadata snapshot requires a non-empty account key".to_string(), + ); + } + if state.kind != crate::DcToken2022StateKind::Mint { + return std::result::Result::Err( + "Token-2022 metadata snapshot requires a parsed mint state".to_string(), + ); + } + let mut outputs = std::vec::Vec::new(); + for entry in &state.extensions { + let projection_kind = match entry.extension_name { + "token_metadata" => std::option::Option::Some("token_metadata"), + "token_group" => std::option::Option::Some("token_group"), + "token_group_member" => std::option::Option::Some("token_group_member"), + _ => std::option::Option::None, + }; + let kind = match projection_kind { + std::option::Option::Some(value) => value, + std::option::Option::None => continue, + }; + outputs.push(crate::MtApiMaterializedOutput { + output_key: format!("token2022_metadata_snapshot:{account_key}:{slot}:{kind}"), + family: crate::MdMaterializedEventFamily::Metadata, + payload_json: serde_json::json!({ + "projectionVersion": 1, + "domain": "spl_token2022_embedded_metadata", + "projectionSemantics": "authoritative_bounded_mint_extension_snapshot", + "idempotenceKey": format!("token2022_metadata:{account_key}:{slot}:{kind}"), + "accountKey": account_key, + "slot": slot, + "programId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "metadataSource": "token2022_embedded_tlv", + "projectionKind": kind, + "extensionType": entry.extension_type, + "extensionName": entry.extension_name, + "valueHex": entry.value_hex, + "valueFields": entry.value_fields, + "externalUriFetched": false, + "identityAuthority": "mint_address", + "finalAccountStateCaptured": true, + "provenance": { + "processorName": "kb_materializer_metadata", + "processorVersion": env!("CARGO_PKG_VERSION"), + "source": "bounded_token2022_state_parser" + } + }), + }); + } + return std::result::Result::Ok(outputs); +} + +/// Materialize one canonical Metaplex `MetadataV1` account snapshot. +/// +/// Account snapshots are authoritative for current state. Instruction observations may describe +/// mutations, but must not emit a second competing metadata-state projection. +pub fn materialize_metaplex_metadata_snapshot( + snapshot: &crate::DcMetadataMtmCanonicalMetadataAccountSnapshot, +) -> std::result::Result { + if !snapshot.provenance.committed { + return std::result::Result::Err( + "Metaplex metadata state materialization requires committed provenance".to_string(), + ); + } + if snapshot.identity.materialization + != crate::DcMetadataMtmCanonicalMaterializationPolicy::ActiveState + { + return std::result::Result::Err( + "Metaplex MetadataV1 materialization requires active-state policy".to_string(), + ); + } + let metadata = match &snapshot.state { + crate::DcMetadataMtmCanonicalMetadataAccountState::Metadata(value) => value, + _ => { + return std::result::Result::Err( + "Metaplex metadata materializer received another account layout".to_string(), + ); + }, + }; + let slot = snapshot.provenance.slot.map(|value| return value.to_string()); + let write_version = snapshot.provenance.write_version.map(|value| return value.to_string()); + let payload = serde_json::json!({ + "projectionVersion": 1, + "domain": "metaplex_token_metadata", + "projectionSemantics": "authoritative_committed_account_snapshot", + "stableId": snapshot.identity.stable_id, + "account": metadata.account, + "mint": metadata.mint, + "updateAuthority": metadata.update_authority, + "name": metadata.name, + "symbol": metadata.symbol, + "uri": metadata.uri, + "sellerFeeBasisPoints": metadata.seller_fee_basis_points, + "primarySaleHappened": metadata.primary_sale_happened, + "isMutable": metadata.is_mutable, + "layout": snapshot.identity.layout, + "layoutDiscriminant": snapshot.identity.discriminant, + "canonicalVersion": snapshot.identity.canonical_version, + "lifecycle": "active", + "materializationPolicy": "active_state", + "metadataSource": "metaplex_owned_account", + "accountState": metadata.payload_json, + "externalUriFetched": false, + "stateAuthority": "owned_account_snapshot", + "instructionProjectionRole": "mutation_observation_only_no_duplicate_state", + "provenance": { + "source": format!("{:?}", snapshot.provenance.source), + "slot": slot, + "writeVersion": write_version, + "signature": snapshot.provenance.signature, + "instructionIndex": snapshot.provenance.instruction_index, + "innerInstructionIndex": snapshot.provenance.inner_instruction_index, + "committed": snapshot.provenance.committed, + "processorName": "kb_materializer_metadata", + "processorVersion": env!("CARGO_PKG_VERSION") + } + }); + return std::result::Result::Ok(crate::MtApiMaterializedOutput { + output_key: format!("metaplex_metadata_state:{}", metadata.account), + family: crate::MdMaterializedEventFamily::Metadata, + payload_json: payload, + }); +} + +#[cfg(test)] +mod tests_metaplex_metadata_state { + pub(super) fn snapshot( + committed: bool, + ) -> crate::DcMetadataMtmCanonicalMetadataAccountSnapshot { + let metadata = crate::DcMetadataMtmMetadataAccountSnapshot { + account: "metadata111".to_string(), + bump: 1, + mint: "mint111".to_string(), + update_authority: "authority111".to_string(), + name: "Asset".to_string(), + symbol: "AST".to_string(), + uri: "https://example.invalid/asset.json".to_string(), + seller_fee_basis_points: 500, + primary_sale_happened: true, + is_mutable: false, + payload_json: serde_json::json!({ + "creators": [{"address":"creator111","verified":true,"share":100}], + "collection": {"verified":true,"key":"collection111"}, + "uses": {"useMethod":"Single","remaining":"0","total":"1"}, + "tokenStandard": "ProgrammableNonFungible", + "programmableConfig": {"ruleSet":"rules111"} + }), + }; + return crate::DcMetadataMtmCanonicalMetadataAccountSnapshot::from_metadata( + metadata, + crate::DcMetadataMtmCanonicalAccountProvenance { + source: crate::DcMetadataMtmCanonicalObservationSource::Backfill, + slot: std::option::Option::Some(42), + write_version: std::option::Option::Some(7), + signature: std::option::Option::Some("signature111".to_string()), + instruction_index: std::option::Option::Some(3), + inner_instruction_index: std::option::Option::None, + committed, + }, + ); + } + + #[test] + fn account_snapshot_is_one_stable_authoritative_metadata_projection() { + let first = crate::materialize_metaplex_metadata_snapshot(&snapshot(true)); + let second = crate::materialize_metaplex_metadata_snapshot(&snapshot(true)); + assert_eq!(first, second); + assert_eq!( + first.as_ref().map(|value| return value.output_key.as_str()), + std::result::Result::Ok("metaplex_metadata_state:metadata111") + ); + assert_eq!( + first.as_ref().map(|value| return value.payload_json["metadataSource"].clone()), + std::result::Result::Ok(serde_json::json!("metaplex_owned_account")) + ); + assert_eq!( + first + .as_ref() + .map(|value| return value.payload_json["instructionProjectionRole"].clone()), + std::result::Result::Ok(serde_json::json!( + "mutation_observation_only_no_duplicate_state" + )) + ); + assert_eq!( + first + .as_ref() + .map(|value| return value.payload_json["accountState"]["creators"][0]["share"] + .clone()), + std::result::Result::Ok(serde_json::json!(100)) + ); + } + + #[test] + fn uncommitted_or_non_metadata_state_is_rejected() { + assert!(crate::materialize_metaplex_metadata_snapshot(&snapshot(false)).is_err()); + let mut wrong = snapshot(true); + wrong.state = crate::DcMetadataMtmCanonicalMetadataAccountState::EditionMarker( + crate::DcMetadataMtmEditionMarkerAccountSnapshot { + account: "marker111".to_string(), + bump: 1, + mint: "mint111".to_string(), + kind: crate::DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV1, + marker_group: std::option::Option::Some(0), + edition: 1, + byte_index: 0, + bit_mask: 64, + edition_taken: true, + ledger: std::vec![64], + payload_json: serde_json::json!({}), + }, + ); + assert!(crate::materialize_metaplex_metadata_snapshot(&wrong).is_err()); + } +} + +/// Materialize any canonical Metaplex account state other than `MetadataV1`. +/// +/// Every account address maps to one stable state key. Historical layouts remain materializable +/// with an explicit historical lifecycle, while execution policy remains independently disabled. +pub fn materialize_metaplex_account_snapshot( + snapshot: &crate::DcMetadataMtmCanonicalMetadataAccountSnapshot, +) -> std::result::Result { + if !snapshot.provenance.committed { + return std::result::Result::Err( + "Metaplex account-state materialization requires committed provenance".to_string(), + ); + } + let (projection_kind, fact_owner, state_json) = match &snapshot.state { + crate::DcMetadataMtmCanonicalMetadataAccountState::Metadata(_) => { + return std::result::Result::Err( + "MetadataV1 must use the dedicated metadata-state materializer".to_string(), + ); + }, + crate::DcMetadataMtmCanonicalMetadataAccountState::Edition(value) => { + ("edition_state", "kb_materializer_metadata", value.payload_json.clone()) + }, + crate::DcMetadataMtmCanonicalMetadataAccountState::EditionMarker(value) => { + ("edition_marker_state", "kb_materializer_metadata", value.payload_json.clone()) + }, + crate::DcMetadataMtmCanonicalMetadataAccountState::TokenRecord(value) => ( + "programmable_token_state", + "kb_materializer_lifecycle", + value.payload_json.clone(), + ), + crate::DcMetadataMtmCanonicalMetadataAccountState::DelegateRecord(value) => { + ("delegate_admin_state", "kb_materializer_admin", value.payload_json.clone()) + }, + crate::DcMetadataMtmCanonicalMetadataAccountState::AuthorityRecord(value) => { + ("authority_admin_state", "kb_materializer_admin", value.payload_json.clone()) + }, + crate::DcMetadataMtmCanonicalMetadataAccountState::TokenOwnedEscrow(value) => ( + "token_owned_escrow_state", + "kb_materializer_lifecycle", + value.payload_json.clone(), + ), + crate::DcMetadataMtmCanonicalMetadataAccountState::ReservationList(value) => ( + "historical_reservation_state", + "kb_materializer_metadata", + value.payload_json.clone(), + ), + }; + let lifecycle = match snapshot.identity.lifecycle { + crate::DcMetadataMtmCanonicalAccountLifecycle::Active => "active", + crate::DcMetadataMtmCanonicalAccountLifecycle::ActiveExperimental => "active_experimental", + crate::DcMetadataMtmCanonicalAccountLifecycle::Historical => "historical", + }; + let materialization_policy = match snapshot.identity.materialization { + crate::DcMetadataMtmCanonicalMaterializationPolicy::ActiveState => "active_state", + crate::DcMetadataMtmCanonicalMaterializationPolicy::HistoricalState => "historical_state", + }; + let execution_policy = match snapshot.identity.execution { + crate::DcMetadataMtmCanonicalExecutionPolicy::CurrentCandidate => "current_candidate", + crate::DcMetadataMtmCanonicalExecutionPolicy::ExperimentalCandidate => { + "experimental_candidate" + }, + crate::DcMetadataMtmCanonicalExecutionPolicy::NeverHistorical => "never_historical", + }; + return std::result::Result::Ok(crate::MtApiMaterializedOutput { + output_key: format!("metaplex_account_state:{}", snapshot.identity.account), + family: crate::MdMaterializedEventFamily::Metadata, + payload_json: serde_json::json!({ + "projectionVersion": 1, + "domain": "metaplex_token_metadata", + "projectionKind": projection_kind, + "projectionSemantics": "authoritative_committed_owned_account_snapshot", + "stableId": snapshot.identity.stable_id, + "account": snapshot.identity.account, + "programId": snapshot.identity.program_id, + "layout": snapshot.identity.layout, + "layoutDiscriminant": snapshot.identity.discriminant, + "canonicalVersion": snapshot.identity.canonical_version, + "lifecycle": lifecycle, + "materializationPolicy": materialization_policy, + "executionPolicy": execution_policy, + "factOwner": fact_owner, + "metadataSource": "metaplex_owned_account", + "accountState": state_json, + "instructionProjectionRole": "mutation_observation_only_no_duplicate_state", + "provenance": { + "source": format!("{:?}", snapshot.provenance.source), + "slot": snapshot.provenance.slot.map(|value: u64| return value.to_string()), + "writeVersion": snapshot.provenance.write_version.map(|value: u64| return value.to_string()), + "signature": snapshot.provenance.signature, + "instructionIndex": snapshot.provenance.instruction_index, + "innerInstructionIndex": snapshot.provenance.inner_instruction_index, + "committed": snapshot.provenance.committed, + "processorName": "kb_materializer_metadata", + "processorVersion": env!("CARGO_PKG_VERSION") + } + }), + }); +} + +#[cfg(test)] +mod tests_metaplex_account_state { + fn provenance() -> crate::DcMetadataMtmCanonicalAccountProvenance { + return crate::DcMetadataMtmCanonicalAccountProvenance { + source: crate::DcMetadataMtmCanonicalObservationSource::Backfill, + slot: std::option::Option::Some(90), + write_version: std::option::Option::Some(2), + signature: std::option::Option::None, + instruction_index: std::option::Option::None, + inner_instruction_index: std::option::Option::None, + committed: true, + }; + } + + #[test] + fn historical_edition_and_reservation_are_stable_materializable_state() { + let edition = crate::DcMetadataMtmCanonicalMetadataAccountSnapshot::from_edition( + crate::DcMetadataMtmEditionAccountSnapshot { + account: "master-v1".to_string(), + bump: 1, + mint: "mint-v1".to_string(), + kind: crate::DcMetadataMtmEditionAccountKind::MasterEditionV1, + supply: std::option::Option::Some(3), + max_supply: std::option::Option::Some(10), + parent: std::option::Option::None, + edition: std::option::Option::None, + printing_mint: std::option::Option::Some("printing".to_string()), + one_time_printing_authorization_mint: std::option::Option::Some( + "authorization".to_string(), + ), + payload_json: serde_json::json!({"supply":"3","maxSupply":"10"}), + }, + provenance(), + ); + let reservation = + crate::DcMetadataMtmCanonicalMetadataAccountSnapshot::from_reservation_list( + crate::DcMetadataMtmReservationListAccountSnapshot { + account: "reservation-v2".to_string(), + bump: 2, + kind: crate::DcMetadataMtmReservationListAccountKind::V2, + master_edition: "master-v1".to_string(), + resource: "resource".to_string(), + supply_snapshot: std::option::Option::Some(3), + reservations: std::vec::Vec::new(), + total_reservation_spots: 0, + current_reservation_spots: 0, + payload_json: serde_json::json!({"reservations":[]}), + }, + provenance(), + ); + let first = crate::materialize_metaplex_account_snapshot(&edition); + let second = crate::materialize_metaplex_account_snapshot(&reservation); + assert_eq!( + first.as_ref().map(|value| return value.payload_json["lifecycle"].clone()), + std::result::Result::Ok(serde_json::json!("historical")) + ); + assert_eq!( + first.as_ref().map(|value| return value.payload_json["executionPolicy"].clone()), + std::result::Result::Ok(serde_json::json!("never_historical")) + ); + assert_eq!( + second.as_ref().map(|value| return value.output_key.as_str()), + std::result::Result::Ok("metaplex_account_state:reservation-v2") + ); + } + + #[test] + fn programmable_delegate_authority_and_escrow_keep_unique_fact_owners() { + let token = crate::DcMetadataMtmCanonicalMetadataAccountSnapshot::from_token_record( + crate::DcMetadataMtmTokenRecordAccountSnapshot { + account: "token-record".to_string(), + bump: 1, + mint: "mint".to_string(), + token: "token".to_string(), + stored_bump: 1, + state: "Locked".to_string(), + rule_set_revision: std::option::Option::Some(4), + delegate: std::option::Option::Some("delegate".to_string()), + delegate_role: std::option::Option::Some("Transfer".to_string()), + locked_transfer: std::option::Option::Some("destination".to_string()), + locked: true, + payload_json: serde_json::json!({"state":"Locked"}), + }, + provenance(), + ); + let output = crate::materialize_metaplex_account_snapshot(&token); + assert_eq!( + output.as_ref().map(|value| return value.payload_json["factOwner"].clone()), + std::result::Result::Ok(serde_json::json!("kb_materializer_lifecycle")) + ); + assert_eq!( + output.as_ref().map(|value| return value.payload_json["projectionKind"].clone()), + std::result::Result::Ok(serde_json::json!("programmable_token_state")) + ); + } + + #[test] + fn uncommitted_and_metadata_snapshots_use_explicit_boundaries() { + let mut marker = crate::DcMetadataMtmCanonicalMetadataAccountSnapshot::from_edition_marker( + crate::DcMetadataMtmEditionMarkerAccountSnapshot { + account: "marker".to_string(), + bump: 1, + mint: "mint".to_string(), + kind: crate::DcMetadataMtmEditionMarkerAccountKind::EditionMarkerV2, + marker_group: std::option::Option::None, + edition: 8, + byte_index: 1, + bit_mask: 128, + edition_taken: true, + ledger: std::vec![0, 128], + payload_json: serde_json::json!({"editionTaken":true}), + }, + provenance(), + ); + marker.provenance.committed = false; + assert!(crate::materialize_metaplex_account_snapshot(&marker).is_err()); + assert!( + crate::materialize_metaplex_account_snapshot( + &super::tests_metaplex_metadata_state::snapshot(true) + ) + .is_err() + ); + } +} + +#[cfg(test)] +mod tests_token2022_state { + #[test] + fn embedded_metadata_group_and_member_have_distinct_stable_outputs() { + let state = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Mint, + base_fields: serde_json::json!({"supply":"1","decimals":0}), + base_hex: "00".repeat(82), + account_type: std::option::Option::Some(1), + extensions: std::vec![ + crate::DcToken2022TlvEntry { + extension_type: 19, + extension_name: "token_metadata", + value_hex: "01".to_string(), + value_fields: serde_json::json!({"name":"Token","symbol":"TOK","uri":"https://example.invalid/token.json"}), + }, + crate::DcToken2022TlvEntry { + extension_type: 20, + extension_name: "token_group", + value_hex: "02".to_string(), + value_fields: serde_json::json!({"mint":"mint111","size":"1","maxSize":"10"}), + }, + crate::DcToken2022TlvEntry { + extension_type: 21, + extension_name: "token_group_member", + value_hex: "03".to_string(), + value_fields: serde_json::json!({"mint":"mint111","group":"group111","memberNumber":"1"}), + }, + ], + }; + let outputs = crate::materialize_token2022_metadata_snapshot("mint111", 9, &state); + assert_eq!(outputs.as_ref().map(|values| return values.len()), std::result::Result::Ok(3)); + assert_eq!( + outputs + .as_ref() + .map(|values| return values[0].payload_json["metadataSource"].clone()), + std::result::Result::Ok(serde_json::json!("token2022_embedded_tlv")) + ); + assert_eq!( + outputs + .as_ref() + .map(|values| return values[0].payload_json["externalUriFetched"].clone()), + std::result::Result::Ok(serde_json::json!(false)) + ); + assert_eq!( + outputs + .as_ref() + .map(|values| return values[1].payload_json["projectionKind"].clone()), + std::result::Result::Ok(serde_json::json!("token_group")) + ); + } + + #[test] + fn snapshot_is_idempotent_filters_unrelated_extensions_and_requires_mint_identity() { + let state = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Mint, + base_fields: serde_json::json!({}), + base_hex: "00".repeat(82), + account_type: std::option::Option::Some(1), + extensions: std::vec![crate::DcToken2022TlvEntry { + extension_type: 1, + extension_name: "transfer_fee_config", + value_hex: "00".to_string(), + value_fields: serde_json::json!({}), + }], + }; + let first = crate::materialize_token2022_metadata_snapshot("mint111", 9, &state); + let second = crate::materialize_token2022_metadata_snapshot("mint111", 9, &state); + assert_eq!(first, second); + assert_eq!(first.as_ref().map(|values| return values.len()), std::result::Result::Ok(0)); + assert!(crate::materialize_token2022_metadata_snapshot("", 9, &state).is_err()); + let account_state = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Account, + base_fields: serde_json::json!({}), + base_hex: "00".repeat(165), + account_type: std::option::Option::None, + extensions: std::vec::Vec::new(), + }; + assert!( + crate::materialize_token2022_metadata_snapshot("account111", 9, &account_state) + .is_err() + ); + } +} diff --git a/kb-lib/src/materializer/nft.rs b/kb-lib/src/materializer/nft.rs index 3220b11..2d615eb 100644 --- a/kb-lib/src/materializer/nft.rs +++ b/kb-lib/src/materializer/nft.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/nft.rs -// version: 1 +// version: 2 //! `nft` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/nft/core.rs b/kb-lib/src/materializer/nft/core.rs index 1a7c28e..31c83c8 100644 --- a/kb-lib/src/materializer/nft/core.rs +++ b/kb-lib/src/materializer/nft/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/nft/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_nft`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_nft"; +const LEGACY_CRATE: &str = "kb_materializer_nft"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/oracle.rs b/kb-lib/src/materializer/oracle.rs index 5bc5504..b0d18a8 100644 --- a/kb-lib/src/materializer/oracle.rs +++ b/kb-lib/src/materializer/oracle.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/oracle.rs -// version: 1 +// version: 2 //! `oracle` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/oracle/core.rs b/kb-lib/src/materializer/oracle/core.rs index c5c37e2..7fa19ba 100644 --- a/kb-lib/src/materializer/oracle/core.rs +++ b/kb-lib/src/materializer/oracle/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/oracle/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_oracle`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_oracle"; +const LEGACY_CRATE: &str = "kb_materializer_oracle"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/orderbook.rs b/kb-lib/src/materializer/orderbook.rs index 8c52bad..6fc67c4 100644 --- a/kb-lib/src/materializer/orderbook.rs +++ b/kb-lib/src/materializer/orderbook.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/orderbook.rs -// version: 1 +// version: 2 //! `orderbook` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/orderbook/core.rs b/kb-lib/src/materializer/orderbook/core.rs index c9690b1..f104c91 100644 --- a/kb-lib/src/materializer/orderbook/core.rs +++ b/kb-lib/src/materializer/orderbook/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/orderbook/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_orderbook`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_orderbook"; +const LEGACY_CRATE: &str = "kb_materializer_orderbook"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/perpetuals.rs b/kb-lib/src/materializer/perpetuals.rs index 79ab60f..f1000da 100644 --- a/kb-lib/src/materializer/perpetuals.rs +++ b/kb-lib/src/materializer/perpetuals.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/perpetuals.rs -// version: 1 +// version: 2 //! `perpetuals` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/perpetuals/core.rs b/kb-lib/src/materializer/perpetuals/core.rs index 632c795..321a421 100644 --- a/kb-lib/src/materializer/perpetuals/core.rs +++ b/kb-lib/src/materializer/perpetuals/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/perpetuals/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_perpetuals`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_perpetuals"; +const LEGACY_CRATE: &str = "kb_materializer_perpetuals"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/pool.rs b/kb-lib/src/materializer/pool.rs index 1802525..b561acf 100644 --- a/kb-lib/src/materializer/pool.rs +++ b/kb-lib/src/materializer/pool.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/pool.rs -// version: 1 +// version: 2 //! `pool` materializer family. -pub mod state; +mod state; diff --git a/kb-lib/src/materializer/pool/state.rs b/kb-lib/src/materializer/pool/state.rs index 98c2472..ad2d1b4 100644 --- a/kb-lib/src/materializer/pool/state.rs +++ b/kb-lib/src/materializer/pool/state.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/pool/state.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_pool_state`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_pool_state"; +const LEGACY_CRATE: &str = "kb_materializer_pool_state"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/rewards.rs b/kb-lib/src/materializer/rewards.rs index 757b67c..91fddba 100644 --- a/kb-lib/src/materializer/rewards.rs +++ b/kb-lib/src/materializer/rewards.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/rewards.rs -// version: 1 +// version: 2 //! `rewards` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/rewards/core.rs b/kb-lib/src/materializer/rewards/core.rs index c2a32b5..27e50f3 100644 --- a/kb-lib/src/materializer/rewards/core.rs +++ b/kb-lib/src/materializer/rewards/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/rewards/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_rewards`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_rewards"; +const LEGACY_CRATE: &str = "kb_materializer_rewards"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/risk.rs b/kb-lib/src/materializer/risk.rs index 5c5802c..937bbfd 100644 --- a/kb-lib/src/materializer/risk.rs +++ b/kb-lib/src/materializer/risk.rs @@ -1,6 +1,17 @@ // file: kb-lib/src/materializer/risk.rs -// version: 1 +// version: 2 //! `risk` materializer family. -pub mod core; +mod constants; +mod core; + +/// Stable processor name for SPL Token and ATA risk facts. +pub(crate) use self::constants::MT_RISK_PROCESSOR_NAME; +/// Stable projection contract version for SPL Token and ATA risk facts. +pub(crate) use self::constants::MT_RISK_PROJECTION_VERSION; +/// Canonical tracing target for SPL Token and ATA risk facts. +pub(crate) use self::constants::MT_RISK_TRACING_TARGET; + +/// Stable SPL Token and ATA risk materializer. +pub use self::core::MtRiskMaterializer; diff --git a/kb-lib/src/materializer/risk/constants.rs b/kb-lib/src/materializer/risk/constants.rs new file mode 100644 index 0000000..d8ebb01 --- /dev/null +++ b/kb-lib/src/materializer/risk/constants.rs @@ -0,0 +1,11 @@ +// file: kb-lib/src/materializer/risk/constants.rs +// version: 1 + +//! Local constants for fact-only risk projections. + +/// Stable processor name persisted by the replay ledger. +pub(crate) const MT_RISK_PROCESSOR_NAME: &str = "spl_token_risk"; +/// Stable projection payload contract version. +pub(crate) const MT_RISK_PROJECTION_VERSION: u32 = 2; +/// Canonical tracing target for this component. +pub(crate) const MT_RISK_TRACING_TARGET: &str = "kb-lib.materializer.risk"; diff --git a/kb-lib/src/materializer/risk/core.rs b/kb-lib/src/materializer/risk/core.rs index 1e75035..8da7b4b 100644 --- a/kb-lib/src/materializer/risk/core.rs +++ b/kb-lib/src/materializer/risk/core.rs @@ -1,10 +1,641 @@ // file: kb-lib/src/materializer/risk/core.rs -// version: 1 +// version: 2 -//! Migration boundary for legacy crate `kb_materializer_risk`. +//! Stable fact-only risk projections for committed SPL Token and ATA observations. -/// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_risk"; +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[ + crate::MdEventFamily::TokenAccount, + crate::MdEventFamily::TokenMint, + crate::MdEventFamily::Admin, + crate::MdEventFamily::Lifecycle, + crate::MdEventFamily::Audit, +]; +const RISK_ENTRIES: &[&str] = &[ + "approve", + "approve_checked", + "revoke", + "freeze_account", + "thaw_account", + "set_authority", + "initialize_multisig", + "initialize_multisig2", + "initialize_default_account_state", + "update_default_account_state", + "enable_required_transfer_memos", + "disable_required_transfer_memos", + "enable_cpi_guard", + "disable_cpi_guard", + "initialize_non_transferable_mint", + "initialize_pausable_config", + "pause", + "resume", + "initialize_permissioned_burn", + "enable_confidential_credits", + "disable_confidential_credits", + "enable_non_confidential_credits", + "disable_non_confidential_credits", +]; -/// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +/// Stable fact-only classic SPL Token risk materializer. +#[derive(Clone, Debug, Default)] +pub struct MtRiskMaterializer; + +impl crate::MtMaterializer for crate::MtRiskMaterializer { + fn materializer_name(&self) -> &'static str { + return "kb_materializer_risk"; + } + fn materializer_version(&self) -> &'static str { + return env!("CARGO_PKG_VERSION"); + } + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { + return accepts_event(event); + } + fn materialize_event( + &self, + _event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + return std::result::Result::Ok(std::vec::Vec::new()); + } +} + +impl crate::MtApiEventMaterializer for crate::MtRiskMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { + name: crate::MT_RISK_PROCESSOR_NAME.to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + }; + } + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { + return ACCEPTED_FAMILIES; + } + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { + return accepts_event(&observation.event); + } + fn transaction_policy( + &self, + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; + } + fn materialize( + &self, + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { + if !accepts_event(&observation.event) { + return crate::MtApiMaterializerExecutionResult::ignored(); + } + if observation.transaction_failed || !observation.observation_committed { + return crate::MtApiMaterializerExecutionResult::refused( + "uncommitted_token_risk_fact_refused", + "failed or uncommitted SPL Token or ATA observations cannot create risk facts", + ); + } + let ata = is_ata_recovery(&observation.event); + if ata && !ata_addresses_valid(&observation.payload_json) { + return crate::MtApiMaterializerExecutionResult::refused( + "invalid_nested_ata_risk_fact_refused", + "nested ATA risk fact requires all three canonical address validations", + ); + } + let operation = observation.event.event_name.0.as_str(); + let parameters = observation + .payload_json + .get("parameters") + .cloned() + .unwrap_or(serde_json::Value::Null); + let accounts = observation + .payload_json + .get("accounts") + .cloned() + .unwrap_or(serde_json::Value::Null); + let authority = observation + .payload_json + .get("authority") + .cloned() + .unwrap_or(serde_json::Value::Null); + let addresses = observation + .payload_json + .get("addresses") + .cloned() + .unwrap_or(serde_json::Value::Null); + let risk_kind = match risk_kind(operation, ¶meters, &accounts) { + std::option::Option::Some(value) => value, + std::option::Option::None => { + return crate::MtApiMaterializerExecutionResult::ignored(); + }, + }; + let output = crate::MtApiMaterializedOutput { + output_key: if ata { + format!("ata_risk_fact:{risk_kind}:0") + } else { + format!("spl_token_risk_fact:{risk_kind}:0") + }, + family: crate::MdMaterializedEventFamily::Risk, + payload_json: serde_json::json!({ + "projectionVersion": crate::MT_RISK_PROJECTION_VERSION, + "domain": if ata { "spl_associated_token_account_risk_fact" } else { "spl_token_risk_fact" }, + "riskKind": risk_kind, + "operation": operation, + "signature": observation.event.signature.0.clone(), + "slot": observation.event.slot.0, + "instructionPath": observation.event.instruction_path.0.clone(), + "programId": observation.event.program_id.0.clone(), + "parameters": parameters, + "accounts": accounts, + "authority": authority, + "addresses": addresses, + "interpretation": { + "score": serde_json::Value::Null, + "severity": serde_json::Value::Null, + "factOnly": true + }, + "committed": true, + "provenance": { + "processorName": crate::MT_RISK_PROCESSOR_NAME, + "processorVersion": env!("CARGO_PKG_VERSION"), + "sourceEventKey": observation.event_key.clone() + } + }), + }; + tracing::debug!(target: crate::MT_RISK_TRACING_TARGET, action = "materialize_token_risk_fact", risk_kind, operation, ata, "materialize committed SPL Token or ATA risk fact"); + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, + outputs: std::vec![output], + diagnostics: std::vec::Vec::new(), + }; + } +} + +fn accepts_event(event: &crate::MdDecodedProtocolEvent) -> bool { + let token_program = (event.program_id.0 == kb_program_ids::SPL_TOKEN_PROGRAM_ID + && event.surface_code.0 == "spl_token") + || (event.program_id.0 == kb_program_ids::SPL_TOKEN2022_PROGRAM_ID + && event.surface_code.0 == "spl_token2022"); + let token_risk = token_program && RISK_ENTRIES.contains(&event.event_name.0.as_str()); + return ACCEPTED_FAMILIES.contains(&event.event_family) + && (token_risk || is_ata_recovery(event)); +} + +fn is_ata_recovery(event: &crate::MdDecodedProtocolEvent) -> bool { + return event.program_id.0 == kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID + && event.surface_code.0 == "spl_associated_token_account" + && event.event_family == crate::MdEventFamily::Lifecycle + && event.event_name.0 == "recover_nested"; +} + +fn ata_addresses_valid(payload: &serde_json::Value) -> bool { + let addresses = match payload.get("addresses") { + std::option::Option::Some(value) => value, + std::option::Option::None => return false, + }; + let token_supported = addresses + .get("tokenProgram") + .and_then(|value| return value.get("supported")) + .and_then(serde_json::Value::as_bool) + == std::option::Option::Some(true); + let token_program_id = addresses + .get("tokenProgram") + .and_then(|value| return value.get("programId")) + .and_then(serde_json::Value::as_str); + let token_program_exact = matches!( + token_program_id, + std::option::Option::Some(kb_program_ids::SPL_TOKEN_PROGRAM_ID) + | std::option::Option::Some(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID) + ); + return token_supported + && token_program_exact + && [ + "ownerAssociatedTokenAccount", + "nestedAssociatedTokenAccount", + "walletNestedMintAssociatedTokenAccount", + ] + .iter() + .all(|field| { + let address = match addresses.get(*field) { + std::option::Option::Some(value) => value, + std::option::Option::None => return false, + }; + return address + .get("observed") + .and_then(serde_json::Value::as_str) + .is_some_and(|value| return !value.is_empty()) + && address.get("valid").and_then(serde_json::Value::as_bool) + == std::option::Option::Some(true); + }); +} + +fn risk_kind( + operation: &str, + parameters: &serde_json::Value, + accounts: &serde_json::Value, +) -> std::option::Option<&'static str> { + return match operation { + "recover_nested" => std::option::Option::Some("nested_ata_anti_pattern_recovered"), + "approve" | "approve_checked" => std::option::Option::Some("delegation_allowance_granted"), + "revoke" => std::option::Option::Some("delegation_revoked"), + "freeze_account" => std::option::Option::Some("account_frozen"), + "thaw_account" => std::option::Option::Some("account_thawed"), + "set_authority" + if parameters.get("newAuthority").is_some_and(serde_json::Value::is_null) => + { + std::option::Option::Some("authority_revoked") + }, + "set_authority" => std::option::Option::Some("authority_changed"), + "initialize_default_account_state" | "update_default_account_state" => { + std::option::Option::Some("default_account_state_configured") + }, + "enable_required_transfer_memos" => { + std::option::Option::Some("required_transfer_memos_enabled") + }, + "disable_required_transfer_memos" => { + std::option::Option::Some("required_transfer_memos_disabled") + }, + "enable_cpi_guard" => std::option::Option::Some("cpi_guard_enabled"), + "disable_cpi_guard" => std::option::Option::Some("cpi_guard_disabled"), + "initialize_non_transferable_mint" => { + std::option::Option::Some("non_transferable_mint_configured") + }, + "initialize_pausable_config" => std::option::Option::Some("pausable_mint_configured"), + "pause" => std::option::Option::Some("mint_activity_paused"), + "resume" => std::option::Option::Some("mint_activity_resumed"), + "initialize_permissioned_burn" => std::option::Option::Some("permissioned_burn_configured"), + "enable_confidential_credits" => std::option::Option::Some("confidential_credits_enabled"), + "disable_confidential_credits" => { + std::option::Option::Some("confidential_credits_disabled") + }, + "enable_non_confidential_credits" => { + std::option::Option::Some("non_confidential_credits_enabled") + }, + "disable_non_confidential_credits" => { + std::option::Option::Some("non_confidential_credits_disabled") + }, + "initialize_multisig" | "initialize_multisig2" => { + let m = parameters.get("m").and_then(serde_json::Value::as_u64).unwrap_or(0); + let n = role_count(accounts, "multisig_member"); + if m == 1 && n > 1 { + std::option::Option::Some("weak_multisig_threshold") + } else { + std::option::Option::None + } + }, + _ => std::option::Option::None, + }; +} + +fn role_count(accounts: &serde_json::Value, role: &str) -> usize { + return accounts + .as_array() + .map(|rows| { + return rows + .iter() + .filter(|row| { + return row.get("role").and_then(serde_json::Value::as_str) + == std::option::Option::Some(role); + }) + .count(); + }) + .unwrap_or(0); +} + +#[cfg(test)] +mod tests { + fn observation( + entry: &str, + family: crate::MdEventFamily, + parameters: serde_json::Value, + failed: bool, + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { + event_key: format!("token:{entry}:0"), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(1), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()), + protocol_code: crate::MdProtocolCode("spl_token".to_string()), + surface_code: crate::MdSurfaceCode("spl_token".to_string()), + event_code: crate::MdEventCode(format!("spl_token.{entry}")), + event_name: crate::MdEventName(entry.to_string()), + event_family: family, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, + }, + payload_json: serde_json::json!({"parameters":parameters,"accounts":[{"role":"multisig_member"},{"role":"multisig_member"}],"authority":{}}), + transaction_failed: failed, + transaction_error: std::option::Option::None, + observation_committed: !failed, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, + evidence: std::vec!["fixture".to_string()], + }, + }; + } + + fn token2022_observation( + entry: &str, + family: crate::MdEventFamily, + parameters: serde_json::Value, + failed: bool, + ) -> crate::DcApiDecodedObservation { + let mut observation = observation(entry, family, parameters, failed); + observation.event.program_id = + crate::MdProgramId(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.to_string()); + observation.event.protocol_code = crate::MdProtocolCode("spl_token2022".to_string()); + observation.event.surface_code = crate::MdSurfaceCode("spl_token2022".to_string()); + observation.event.event_code = crate::MdEventCode(format!("spl_token2022.{entry}")); + observation.event_key = format!("token2022:{entry}:0"); + return observation; + } + + fn nested_ata_observation(failed: bool, valid: bool) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { + event_key: "ata:recover_nested:0".to_string(), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(2), + instruction_path: crate::MdInstructionPath("1/0".to_string()), + program_id: crate::MdProgramId( + kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string(), + ), + protocol_code: crate::MdProtocolCode("spl_associated_token_account".to_string()), + surface_code: crate::MdSurfaceCode("spl_associated_token_account".to_string()), + event_code: crate::MdEventCode( + "spl_associated_token_account.recover_nested".to_string(), + ), + event_name: crate::MdEventName("recover_nested".to_string()), + event_family: crate::MdEventFamily::Lifecycle, + source_kind: crate::MdEventSourceKind::InnerInstruction, + confidence: crate::MdDecoderConfidence::ManualExact, + }, + payload_json: serde_json::json!({ + "addresses": { + "tokenProgram": { + "programId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "kind": "token2022", + "supported": true + }, + "ownerAssociatedTokenAccount": {"observed":"ownerAta","valid":valid}, + "nestedAssociatedTokenAccount": {"observed":"nestedAta","valid":valid}, + "walletNestedMintAssociatedTokenAccount": {"observed":"destinationAta","valid":valid} + } + }), + transaction_failed: failed, + transaction_error: std::option::Option::None, + observation_committed: !failed, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, + evidence: std::vec!["fixture".to_string()], + }, + }; + } + + #[test] + fn approval_and_authority_revocation_are_fact_only_without_score() { + for (entry, family, parameters, expected) in [ + ( + "approve_checked", + crate::MdEventFamily::TokenAccount, + serde_json::json!({"amountRaw":"10"}), + "delegation_allowance_granted", + ), + ( + "set_authority", + crate::MdEventFamily::Admin, + serde_json::json!({"newAuthority":null}), + "authority_revoked", + ), + ] { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtRiskMaterializer, + &observation(entry, family, parameters, false), + ); + assert_eq!(result.outputs[0].payload_json["riskKind"], expected); + assert!(result.outputs[0].payload_json["interpretation"]["score"].is_null()); + } + } + + #[test] + fn token2022_revocation_is_owned_once_without_an_invented_score() { + let observation = token2022_observation( + "set_authority", + crate::MdEventFamily::Admin, + serde_json::json!({"newAuthority":null}), + false, + ); + let result = + crate::MtApiEventMaterializer::materialize(&crate::MtRiskMaterializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs.len(), 1); + assert_eq!(result.outputs[0].payload_json["riskKind"], "authority_revoked"); + assert!(result.outputs[0].payload_json["interpretation"]["score"].is_null()); + } + + #[test] + fn only_structurally_weak_multisig_creates_risk_fact() { + let weak = observation( + "initialize_multisig2", + crate::MdEventFamily::Admin, + serde_json::json!({"m":1}), + false, + ); + let strong = observation( + "initialize_multisig2", + crate::MdEventFamily::Admin, + serde_json::json!({"m":2}), + false, + ); + assert_eq!( + crate::MtApiEventMaterializer::materialize(&crate::MtRiskMaterializer, &weak).status, + crate::MtApiMaterializerOutcomeStatus::Inserted + ); + assert_eq!( + crate::MtApiEventMaterializer::materialize(&crate::MtRiskMaterializer, &strong).status, + crate::MtApiMaterializerOutcomeStatus::Ignored + ); + } + + #[test] + fn failed_risk_fact_is_refused() { + let failed = observation( + "freeze_account", + crate::MdEventFamily::TokenAccount, + serde_json::json!({}), + true, + ); + assert_eq!( + crate::MtApiEventMaterializer::materialize(&crate::MtRiskMaterializer, &failed).status, + crate::MtApiMaterializerOutcomeStatus::Refused + ); + } + + #[test] + fn committed_nested_ata_recovery_creates_one_fact_without_score() { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtRiskMaterializer, + &nested_ata_observation(false, true), + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs.len(), 1); + assert_eq!( + result.outputs[0].output_key, + "ata_risk_fact:nested_ata_anti_pattern_recovered:0" + ); + assert_eq!(result.outputs[0].payload_json["riskKind"], "nested_ata_anti_pattern_recovered"); + assert_eq!( + result.outputs[0].payload_json["domain"], + "spl_associated_token_account_risk_fact" + ); + assert!(result.outputs[0].payload_json["interpretation"]["score"].is_null()); + assert!(result.outputs[0].payload_json["interpretation"]["severity"].is_null()); + } + + #[test] + fn failed_or_invalid_nested_ata_recovery_creates_no_risk_fact() { + for observation in + [nested_ata_observation(true, true), nested_ata_observation(false, false)] + { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtRiskMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); + assert!(result.outputs.is_empty()); + } + } + + #[test] + fn ata_matrix_declares_the_single_compiled_risk_fact() { + let matrix: serde_json::Value = match serde_json::from_str(include_str!( + "../../../../docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json" + )) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("ATA matrix is invalid: {error}"), + }; + let instructions = match matrix["instructions"].as_array() { + std::option::Option::Some(value) => value, + std::option::Option::None => panic!("ATA matrix instructions are absent"), + }; + let recover = match instructions.iter().find(|row| { + return row.get("name").and_then(serde_json::Value::as_str) + == std::option::Option::Some("recover_nested"); + }) { + std::option::Option::Some(value) => value, + std::option::Option::None => panic!("RecoverNested matrix entry is absent"), + }; + assert!(recover["authorizedProjections"].as_array().is_some_and(|values| { + return values.iter().any(|value| { + return value == "risk:nested_ata_anti_pattern_recovered"; + }); + })); + assert_eq!( + matrix["materializationContract"]["projectionOwners"][1]["facts"], + serde_json::json!(["nested_ata_anti_pattern_recovered"]) + ); + } + + #[test] + fn token2022_compliance_toggles_are_projected_as_fact_only_risk_rows() { + for (entry, expected) in [ + ("initialize_default_account_state", "default_account_state_configured"), + ("enable_required_transfer_memos", "required_transfer_memos_enabled"), + ("disable_required_transfer_memos", "required_transfer_memos_disabled"), + ("enable_cpi_guard", "cpi_guard_enabled"), + ("disable_cpi_guard", "cpi_guard_disabled"), + ] { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtRiskMaterializer, + &token2022_observation( + entry, + crate::MdEventFamily::Audit, + serde_json::json!({}), + false, + ), + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs[0].payload_json["riskKind"], expected); + assert_eq!(result.outputs[0].payload_json["interpretation"]["factOnly"], true); + assert!(result.outputs[0].payload_json["interpretation"]["score"].is_null()); + } + } + + #[test] + fn token2022_restriction_and_pause_facts_have_unique_stable_kinds() { + for (entry, family, expected) in [ + ( + "initialize_non_transferable_mint", + crate::MdEventFamily::TokenMint, + "non_transferable_mint_configured", + ), + ( + "initialize_pausable_config", + crate::MdEventFamily::TokenAccount, + "pausable_mint_configured", + ), + ("pause", crate::MdEventFamily::TokenAccount, "mint_activity_paused"), + ("resume", crate::MdEventFamily::TokenAccount, "mint_activity_resumed"), + ( + "initialize_permissioned_burn", + crate::MdEventFamily::TokenAccount, + "permissioned_burn_configured", + ), + ] { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtRiskMaterializer, + &token2022_observation(entry, family, serde_json::json!({}), false), + ); + assert_eq!(result.outputs[0].payload_json["riskKind"], expected); + } + } + #[test] + fn confidential_credit_toggles_are_fact_only_and_keep_wire_parameters() { + for (entry, credit_kind, enabled, expected) in [ + ( + "enable_confidential_credits", + "confidential", + true, + "confidential_credits_enabled", + ), + ( + "disable_confidential_credits", + "confidential", + false, + "confidential_credits_disabled", + ), + ( + "enable_non_confidential_credits", + "non_confidential", + true, + "non_confidential_credits_enabled", + ), + ( + "disable_non_confidential_credits", + "non_confidential", + false, + "non_confidential_credits_disabled", + ), + ] { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtRiskMaterializer, + &token2022_observation( + entry, + crate::MdEventFamily::TokenAccount, + serde_json::json!({ + "extension":"confidential_transfer", + "creditKind":credit_kind, + "enabled":enabled, + }), + false, + ), + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs.len(), 1); + assert_eq!(result.outputs[0].payload_json["riskKind"], expected); + assert_eq!(result.outputs[0].payload_json["parameters"]["creditKind"], credit_kind); + assert_eq!(result.outputs[0].payload_json["parameters"]["enabled"], enabled); + assert_eq!(result.outputs[0].payload_json["interpretation"]["factOnly"], true); + assert!(result.outputs[0].payload_json["interpretation"]["score"].is_null()); + } + } +} diff --git a/kb-lib/src/materializer/routing.rs b/kb-lib/src/materializer/routing.rs index 7c72e13..eea8bb9 100644 --- a/kb-lib/src/materializer/routing.rs +++ b/kb-lib/src/materializer/routing.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/routing.rs -// version: 1 +// version: 2 //! `routing` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/routing/core.rs b/kb-lib/src/materializer/routing/core.rs index 832960f..137d00c 100644 --- a/kb-lib/src/materializer/routing/core.rs +++ b/kb-lib/src/materializer/routing/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/routing/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_routing`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_routing"; +const LEGACY_CRATE: &str = "kb_materializer_routing"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/staking.rs b/kb-lib/src/materializer/staking.rs index 05bf404..8c8f7a2 100644 --- a/kb-lib/src/materializer/staking.rs +++ b/kb-lib/src/materializer/staking.rs @@ -1,12 +1,13 @@ // file: kb-lib/src/materializer/staking.rs -// version: 2 +// version: 3 //! `staking` materializer family. mod constants; -pub mod core; +mod core; -pub(crate) use crate::materializer::staking::constants::TRACING_TARGET as MATERIALIZER_STAKING_TRACING_TARGET; +/// Canonical tracing target for the native stake and vote materializer. +pub(crate) use self::constants::MT_STAKING_TRACING_TARGET; /// Stable native stake and vote materializer. -pub use crate::materializer::staking::core::StakingMaterializer; +pub use self::core::MtStakingMaterializer; diff --git a/kb-lib/src/materializer/staking/constants.rs b/kb-lib/src/materializer/staking/constants.rs index a75272e..5be4894 100644 --- a/kb-lib/src/materializer/staking/constants.rs +++ b/kb-lib/src/materializer/staking/constants.rs @@ -4,4 +4,4 @@ //! Local constants for the native stake and vote materializer. /// Canonical tracing target for this component. -pub(crate) const TRACING_TARGET: &str = "kb-lib.materializer.staking"; +pub(crate) const MT_STAKING_TRACING_TARGET: &str = "kb-lib.materializer.staking"; diff --git a/kb-lib/src/materializer/staking/core.rs b/kb-lib/src/materializer/staking/core.rs index e7438f8..4ea45ec 100644 --- a/kb-lib/src/materializer/staking/core.rs +++ b/kb-lib/src/materializer/staking/core.rs @@ -3,11 +3,11 @@ //! Instruction-level staking projections for native Stake and Vote observations. -const ACCEPTED_FAMILIES: &[crate::EventFamily] = &[ - crate::EventFamily::Lifecycle, - crate::EventFamily::Admin, - crate::EventFamily::Staking, - crate::EventFamily::Reward, +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[ + crate::MdEventFamily::Lifecycle, + crate::MdEventFamily::Admin, + crate::MdEventFamily::Staking, + crate::MdEventFamily::Reward, ]; const STAKE_SURFACE: &str = "solana_native_stake"; const VOTE_SURFACE: &str = "solana_native_vote"; @@ -82,10 +82,10 @@ impl ProjectionKind { }; } - fn family(self) -> crate::MaterializedEventFamily { + fn family(self) -> crate::MdMaterializedEventFamily { return match self { - Self::VoteReward => crate::MaterializedEventFamily::Reward, - _ => crate::MaterializedEventFamily::Staking, + Self::VoteReward => crate::MdMaterializedEventFamily::Reward, + _ => crate::MdMaterializedEventFamily::Staking, }; } @@ -96,9 +96,9 @@ impl ProjectionKind { /// Stable staking materializer for committed native Stake and Vote observations. #[derive(Clone, Debug, Default)] -pub struct StakingMaterializer; +pub struct MtStakingMaterializer; -impl crate::Materializer for crate::StakingMaterializer { +impl crate::MtMaterializer for crate::MtStakingMaterializer { fn materializer_name(&self) -> &'static str { return "kb_materializer_staking"; } @@ -107,35 +107,35 @@ impl crate::Materializer for crate::StakingMaterializer { return env!("CARGO_PKG_VERSION"); } - fn accepts_event(&self, event: &crate::DecodedProtocolEvent) -> bool { + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { return family_is_accepted(event.event_family) && projection(event.surface_code.0.as_str(), event.event_name.0.as_str()).is_some(); } fn materialize_event( &self, - event: &crate::DecodedProtocolEvent, - ) -> kb_core::Result> { - if !crate::Materializer::accepts_event(self, event) { + event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + if !crate::MtMaterializer::accepts_event(self, event) { return std::result::Result::Ok(std::vec::Vec::new()); } return std::result::Result::Ok(std::vec::Vec::new()); } } -impl crate::EventMaterializer for crate::StakingMaterializer { - fn identity(&self) -> crate::MaterializerIdentity { - return crate::MaterializerIdentity { +impl crate::MtApiEventMaterializer for crate::MtStakingMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { name: "solana_native_staking".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } - fn accepted_families(&self) -> &'static [crate::EventFamily] { + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { return ACCEPTED_FAMILIES; } - fn accepts_observation(&self, observation: &crate::DecodedObservation) -> bool { + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { return family_is_accepted(observation.event.event_family) && projection( observation.event.surface_code.0.as_str(), @@ -146,15 +146,15 @@ impl crate::EventMaterializer for crate::StakingMaterializer { fn transaction_policy( &self, - _family: crate::EventFamily, - ) -> crate::MaterializationTransactionPolicy { - return crate::MaterializationTransactionPolicy::SuccessfulCommittedOnly; + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; } fn materialize( &self, - observation: &crate::DecodedObservation, - ) -> crate::MaterializerExecutionResult { + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { let projection = match projection( observation.event.surface_code.0.as_str(), observation.event.event_name.0.as_str(), @@ -162,22 +162,22 @@ impl crate::EventMaterializer for crate::StakingMaterializer { std::option::Option::Some(value) => value, std::option::Option::None => { tracing::debug!( - target: crate::MATERIALIZER_STAKING_TRACING_TARGET, + target: crate::MT_STAKING_TRACING_TARGET, action = "materialize_staking", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), accepted = false, "ignore observation outside supported native staking projections" ); - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); }, }; if !family_is_accepted(observation.event.event_family) { - return crate::MaterializerExecutionResult::ignored(); + return crate::MtApiMaterializerExecutionResult::ignored(); } if observation.transaction_failed || !observation.observation_committed { tracing::debug!( - target: crate::MATERIALIZER_STAKING_TRACING_TARGET, + target: crate::MT_STAKING_TRACING_TARGET, action = "materialize_staking", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -185,7 +185,7 @@ impl crate::EventMaterializer for crate::StakingMaterializer { transaction_failed = observation.transaction_failed, "refuse uncommitted native staking observation" ); - return crate::MaterializerExecutionResult::refused( + return crate::MtApiMaterializerExecutionResult::refused( "failed_transaction_staking_refused", "failed or uncommitted native Stake/Vote observations cannot create staking outputs", ); @@ -201,7 +201,7 @@ impl crate::EventMaterializer for crate::StakingMaterializer { .cloned() .unwrap_or(serde_json::Value::Null); let operation = observation.event.event_name.0.clone(); - let output = crate::MaterializedOutput { + let output = crate::MtApiMaterializedOutput { output_key: projection.output_key(operation.as_str()), family: projection.family(), payload_json: serde_json::json!({ @@ -225,7 +225,7 @@ impl crate::EventMaterializer for crate::StakingMaterializer { }), }; tracing::debug!( - target: crate::MATERIALIZER_STAKING_TRACING_TARGET, + target: crate::MT_STAKING_TRACING_TARGET, action = "materialize_staking", surface_code = %observation.event.surface_code.0.as_str(), entry_code = %observation.event.event_name.0.as_str(), @@ -233,15 +233,15 @@ impl crate::EventMaterializer for crate::StakingMaterializer { output_count = 1_usize, "materialize committed native staking observation" ); - return crate::MaterializerExecutionResult { - status: crate::MaterializerOutcomeStatus::Inserted, + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, outputs: std::vec![output], diagnostics: std::vec::Vec::new(), }; } } -fn family_is_accepted(family: crate::EventFamily) -> bool { +fn family_is_accepted(family: crate::MdEventFamily) -> bool { return ACCEPTED_FAMILIES.iter().any(|accepted| return *accepted == family); } @@ -593,25 +593,25 @@ mod tests { fn observation( surface_code: &str, entry_code: &str, - family: crate::EventFamily, + family: crate::MdEventFamily, transaction_failed: bool, accounts: serde_json::Value, parameters: serde_json::Value, - ) -> crate::DecodedObservation { - return crate::DecodedObservation { + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { event_key: format!("{entry_code}:0"), - event: crate::DecodedProtocolEvent { - signature: crate::Signature("signature".to_string()), - slot: crate::Slot(42), - instruction_path: crate::InstructionPath("0".to_string()), - program_id: crate::ProgramId("program-id".to_string()), - protocol_code: crate::ProtocolCode("solana_native".to_string()), - surface_code: crate::SurfaceCode(surface_code.to_string()), - event_code: crate::EventCode(format!("{surface_code}.{entry_code}")), - event_name: crate::EventName(entry_code.to_string()), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId("program-id".to_string()), + protocol_code: crate::MdProtocolCode("solana_native".to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")), + event_name: crate::MdEventName(entry_code.to_string()), event_family: family, - source_kind: crate::EventSourceKind::Instruction, - confidence: crate::DecoderConfidence::ManualExact, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, }, payload_json: serde_json::json!({"accounts": accounts, "parameters": parameters}), transaction_failed, @@ -621,9 +621,9 @@ mod tests { std::option::Option::None }, observation_committed: !transaction_failed, - proof: crate::DecoderProof { - kind: crate::DecoderProofKind::Manual, - confidence: crate::DecoderConfidence::ManualExact, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec!["fixture".to_string()], }, }; @@ -635,18 +635,18 @@ mod tests { #[test] fn stake_initialize_creates_instructional_staking_projection() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let observation = observation( super::STAKE_SURFACE, "initialize", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, serde_json::json!([account("stake_account", "stake111")]), serde_json::json!({"authorized": {"staker": "staker111"}}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted); - assert_eq!(result.outputs[0].family, crate::MaterializedEventFamily::Staking); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs[0].family, crate::MdMaterializedEventFamily::Staking); assert_eq!(result.outputs[0].output_key, "stake_account:initialize:0"); assert_eq!(result.outputs[0].payload_json["projection"]["stakeAccount"], "stake111"); assert_eq!( @@ -657,11 +657,11 @@ mod tests { #[test] fn stake_authority_and_lockup_events_are_projected() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let authority = observation( super::STAKE_SURFACE, "authorize_with_seed", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, serde_json::json!([account("stake_account", "stake111")]), serde_json::json!({ @@ -674,7 +674,7 @@ mod tests { let lockup = observation( super::STAKE_SURFACE, "set_lockup_checked", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, serde_json::json!([ account("stake_account", "stake111"), @@ -682,8 +682,9 @@ mod tests { ]), serde_json::json!({"epoch": 42}), ); - let authority_result = crate::EventMaterializer::materialize(&materializer, &authority); - let lockup_result = crate::EventMaterializer::materialize(&materializer, &lockup); + let authority_result = + crate::MtApiEventMaterializer::materialize(&materializer, &authority); + let lockup_result = crate::MtApiEventMaterializer::materialize(&materializer, &lockup); assert_eq!(authority_result.outputs[0].output_key, "stake_authority:authorize_with_seed:0"); assert_eq!( authority_result.outputs[0].payload_json["projection"]["newAuthority"], @@ -698,11 +699,11 @@ mod tests { #[test] fn stake_value_projection_does_not_duplicate_lamport_changes() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let observation = observation( super::STAKE_SURFACE, "withdraw", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, serde_json::json!([ account("stake_account", "stake111"), @@ -710,7 +711,7 @@ mod tests { ]), serde_json::json!({"lamports": 99}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); assert_eq!(result.outputs[0].output_key, "stake_value:withdraw:0"); assert_eq!(result.outputs[0].payload_json["projection"]["lamports"], 99); assert_eq!( @@ -721,11 +722,11 @@ mod tests { #[test] fn vote_account_and_authority_events_are_projected() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let initialize = observation( super::VOTE_SURFACE, "initialize_account_v2", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, serde_json::json!([ account("vote_account", "vote111"), @@ -740,7 +741,7 @@ mod tests { let authorize = observation( super::VOTE_SURFACE, "authorize_checked", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, serde_json::json!([ account("vote_account", "vote111"), @@ -748,8 +749,10 @@ mod tests { ]), serde_json::json!({"authorizationType": {"kind": "voter"}, "newAuthorityFromAccount": true}), ); - let initialize_result = crate::EventMaterializer::materialize(&materializer, &initialize); - let authorize_result = crate::EventMaterializer::materialize(&materializer, &authorize); + let initialize_result = + crate::MtApiEventMaterializer::materialize(&materializer, &initialize); + let authorize_result = + crate::MtApiEventMaterializer::materialize(&materializer, &authorize); assert_eq!(initialize_result.outputs[0].output_key, "vote_account:initialize_account_v2:0"); assert_eq!( initialize_result.outputs[0].payload_json["projection"]["validatorIdentity"], @@ -764,11 +767,11 @@ mod tests { #[test] fn vote_state_and_reward_outputs_are_distinguished() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let vote_state = observation( super::VOTE_SURFACE, "tower_sync_switch", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, serde_json::json!([ account("vote_account", "vote111"), @@ -779,7 +782,7 @@ mod tests { let reward = observation( super::VOTE_SURFACE, "deposit_delegator_rewards", - crate::EventFamily::Reward, + crate::MdEventFamily::Reward, false, serde_json::json!([ account("vote_account", "vote111"), @@ -787,40 +790,40 @@ mod tests { ]), serde_json::json!({"depositLamports": 123}), ); - let vote_result = crate::EventMaterializer::materialize(&materializer, &vote_state); - let reward_result = crate::EventMaterializer::materialize(&materializer, &reward); + let vote_result = crate::MtApiEventMaterializer::materialize(&materializer, &vote_state); + let reward_result = crate::MtApiEventMaterializer::materialize(&materializer, &reward); assert_eq!(vote_result.outputs[0].output_key, "vote_state:tower_sync_switch:0"); assert_eq!( vote_result.outputs[0].payload_json["projection"]["switchProofHash"], "switch111" ); - assert_eq!(reward_result.outputs[0].family, crate::MaterializedEventFamily::Reward); + assert_eq!(reward_result.outputs[0].family, crate::MdMaterializedEventFamily::Reward); assert_eq!(reward_result.outputs[0].output_key, "vote_reward:deposit_delegator_rewards:0"); } #[test] fn failed_staking_mutation_is_refused() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let observation = observation( super::STAKE_SURFACE, "delegate_stake", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, true, serde_json::json!([account("stake_account", "stake111")]), serde_json::json!({}), ); - let result = crate::EventMaterializer::materialize(&materializer, &observation); - assert_eq!(result.status, crate::MaterializerOutcomeStatus::Refused); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); assert!(result.outputs.is_empty()); } #[test] fn unrelated_or_disabled_observations_are_ignored() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let unrelated = observation( "solana_native_system", "create_account", - crate::EventFamily::Lifecycle, + crate::MdEventFamily::Lifecycle, false, serde_json::json!([]), serde_json::json!({}), @@ -828,30 +831,32 @@ mod tests { let redelegate = observation( super::STAKE_SURFACE, "redelegate", - crate::EventFamily::Staking, + crate::MdEventFamily::Staking, false, serde_json::json!([]), serde_json::json!({"officiallyDisabled": true}), ); - let unrelated_result = crate::EventMaterializer::materialize(&materializer, &unrelated); - let redelegate_result = crate::EventMaterializer::materialize(&materializer, &redelegate); - assert_eq!(unrelated_result.status, crate::MaterializerOutcomeStatus::Ignored); - assert_eq!(redelegate_result.status, crate::MaterializerOutcomeStatus::Ignored); + let unrelated_result = + crate::MtApiEventMaterializer::materialize(&materializer, &unrelated); + let redelegate_result = + crate::MtApiEventMaterializer::materialize(&materializer, &redelegate); + assert_eq!(unrelated_result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); + assert_eq!(redelegate_result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); } #[test] fn output_serialization_is_deterministic() { - let materializer = crate::StakingMaterializer; + let materializer = crate::MtStakingMaterializer; let observation = observation( super::VOTE_SURFACE, "update_commission_bps", - crate::EventFamily::Admin, + crate::MdEventFamily::Admin, false, serde_json::json!([account("vote_account", "vote111")]), serde_json::json!({"commissionBasisPoints": 250, "commissionKind": "inflation_rewards"}), ); - let first = crate::EventMaterializer::materialize(&materializer, &observation); - let second = crate::EventMaterializer::materialize(&materializer, &observation); + let first = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + let second = crate::MtApiEventMaterializer::materialize(&materializer, &observation); let first_json_result = serde_json::to_string(&first.outputs[0].payload_json); let first_json = match first_json_result { std::result::Result::Ok(value) => value, diff --git a/kb-lib/src/materializer/token.rs b/kb-lib/src/materializer/token.rs index f141bbb..cfd8112 100644 --- a/kb-lib/src/materializer/token.rs +++ b/kb-lib/src/materializer/token.rs @@ -1,7 +1,20 @@ // file: kb-lib/src/materializer/token.rs -// version: 1 +// version: 2 //! `token` materializer family. -pub mod accounts; -pub mod metadata_risk; +mod accounts; +mod constants; +mod metadata_risk; + +/// Stable processor name for Token, ATA and Token-2022 account projections. +pub(crate) use self::constants::MT_TOKEN_ACCOUNTS_PROCESSOR_NAME; +/// Stable projection contract version for Token, ATA and Token-2022 account projections. +pub(crate) use self::constants::MT_TOKEN_ACCOUNTS_PROJECTION_VERSION; +/// Canonical tracing target for Token, ATA and Token-2022 account projections. +pub(crate) use self::constants::MT_TOKEN_ACCOUNTS_TRACING_TARGET; + +/// Stable Token, ATA and Token-2022 account materializer. +pub use self::accounts::MtTokenAccountsMaterializer; +/// Materializes one bounded Token-2022 account state snapshot. +pub use self::accounts::materialize_token2022_state_snapshot; diff --git a/kb-lib/src/materializer/token/accounts.rs b/kb-lib/src/materializer/token/accounts.rs index 9ce6749..55797d2 100644 --- a/kb-lib/src/materializer/token/accounts.rs +++ b/kb-lib/src/materializer/token/accounts.rs @@ -1,10 +1,831 @@ // file: kb-lib/src/materializer/token/accounts.rs -// version: 1 +// version: 2 -//! Migration boundary for legacy crate `kb_materializer_token_accounts`. +//! Stable committed SPL Token mutation and ATA lifecycle projections. -/// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_token_accounts"; +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[ + crate::MdEventFamily::TokenAccount, + crate::MdEventFamily::TokenMint, + crate::MdEventFamily::TokenBurn, + crate::MdEventFamily::Lifecycle, +]; -/// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MUTATION_ENTRIES: &[&str] = &[ + "initialize_mint", + "initialize_mint2", + "initialize_account", + "initialize_account2", + "initialize_account3", + "transfer", + "transfer_checked", + "approve", + "approve_checked", + "revoke", + "mint_to", + "mint_to_checked", + "burn", + "burn_checked", + "close_account", + "freeze_account", + "thaw_account", + "sync_native", + "initialize_immutable_owner", + "withdraw_excess_lamports", + "unwrap_lamports", + "initialize_non_transferable_mint", + "reallocate", +]; +const ATA_LIFECYCLE_ENTRIES: &[(&str, &str)] = &[ + ("create", "ata_created"), + ("create_idempotent", "ata_created_or_reused_idempotently"), + ("recover_nested", "nested_ata_recovered"), +]; + +/// Stable committed classic SPL Token account and mint mutation materializer. +#[derive(Clone, Debug, Default)] +pub struct MtTokenAccountsMaterializer; + +impl crate::MtMaterializer for crate::MtTokenAccountsMaterializer { + fn materializer_name(&self) -> &'static str { + return "kb_materializer_token_accounts"; + } + + fn materializer_version(&self) -> &'static str { + return env!("CARGO_PKG_VERSION"); + } + + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { + return accepts_event(event); + } + + fn materialize_event( + &self, + _event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + return std::result::Result::Ok(std::vec::Vec::new()); + } +} + +impl crate::MtApiEventMaterializer for crate::MtTokenAccountsMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { + name: crate::MT_TOKEN_ACCOUNTS_PROCESSOR_NAME.to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + }; + } + + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { + return ACCEPTED_FAMILIES; + } + + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { + return accepts_event(&observation.event); + } + + fn transaction_policy( + &self, + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; + } + + fn materialize( + &self, + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { + if !accepts_event(&observation.event) { + return crate::MtApiMaterializerExecutionResult::ignored(); + } + if observation.transaction_failed || !observation.observation_committed { + return crate::MtApiMaterializerExecutionResult::refused( + "uncommitted_token_account_projection_refused", + "failed or uncommitted SPL Token or ATA observations cannot create mutable outputs", + ); + } + if is_ata_event(&observation.event) { + return materialize_ata(observation); + } + let parameters = observation + .payload_json + .get("parameters") + .cloned() + .unwrap_or(serde_json::Value::Null); + let accounts = observation + .payload_json + .get("accounts") + .cloned() + .unwrap_or(serde_json::Value::Null); + let authority = observation + .payload_json + .get("authority") + .cloned() + .unwrap_or(serde_json::Value::Null); + let operation = observation.event.event_name.0.clone(); + let output = crate::MtApiMaterializedOutput { + output_key: format!("token_account_mutation:{operation}:0"), + family: crate::MdMaterializedEventFamily::TokenAccount, + payload_json: serde_json::json!({ + "projectionVersion": crate::MT_TOKEN_ACCOUNTS_PROJECTION_VERSION, + "domain": "spl_token_account_mutation", + "projectionSemantics": "committed_instruction_mutation_not_final_account_snapshot", + "idempotenceKey": format!( + "spl_token:{}:{}:{}", + observation.event.signature.0, + observation.event.instruction_path.0, + operation + ), + "operation": operation, + "signature": observation.event.signature.0.clone(), + "slot": observation.event.slot.0, + "instructionPath": observation.event.instruction_path.0.clone(), + "programId": observation.event.program_id.0.clone(), + "mint": account_key_for_role(&accounts, "mint"), + "amountRaw": parameters.get("amountRaw").cloned().unwrap_or(serde_json::Value::Null), + "decimals": parameters.get("decimals").cloned().unwrap_or(serde_json::Value::Null), + "parameters": parameters, + "accounts": accounts, + "authority": authority, + "committed": true, + "transactionFinalAccountStateCaptured": false, + "coreBalanceChangesDuplicated": false, + "provenance": { + "processorName": crate::MT_TOKEN_ACCOUNTS_PROCESSOR_NAME, + "processorVersion": env!("CARGO_PKG_VERSION"), + "sourceSurface": observation.event.surface_code.0.clone(), + "sourceEventCode": observation.event.event_code.0.clone(), + "sourceEventKey": observation.event_key.clone() + } + }), + }; + tracing::debug!( + target: crate::MT_TOKEN_ACCOUNTS_TRACING_TARGET, + action = "materialize_token_account_mutation", + signature = %observation.event.signature.0, + instruction_path = %observation.event.instruction_path.0, + operation = %observation.event.event_name.0, + "materialize committed classic SPL Token mutation" + ); + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, + outputs: std::vec![output], + diagnostics: std::vec::Vec::new(), + }; + } +} + +fn accepts_event(event: &crate::MdDecodedProtocolEvent) -> bool { + let token_program = (event.program_id.0 == kb_program_ids::SPL_TOKEN_PROGRAM_ID + && event.surface_code.0 == "spl_token") + || (event.program_id.0 == kb_program_ids::SPL_TOKEN2022_PROGRAM_ID + && event.surface_code.0 == "spl_token2022"); + let token_mutation = token_program && MUTATION_ENTRIES.contains(&event.event_name.0.as_str()); + let ata = is_ata_event(event); + return ACCEPTED_FAMILIES.contains(&event.event_family) && (token_mutation || ata); +} + +fn is_ata_event(event: &crate::MdDecodedProtocolEvent) -> bool { + return event.program_id.0 == kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID + && event.surface_code.0 == "spl_associated_token_account" + && event.event_family == crate::MdEventFamily::Lifecycle + && ATA_LIFECYCLE_ENTRIES + .iter() + .any(|(entry, _)| return *entry == event.event_name.0); +} + +fn materialize_ata( + observation: &crate::DcApiDecodedObservation, +) -> crate::MtApiMaterializerExecutionResult { + let operation = observation.event.event_name.0.as_str(); + let addresses = match observation.payload_json.get("addresses") { + std::option::Option::Some(value) if value.is_object() => value, + _ => { + return crate::MtApiMaterializerExecutionResult::refused( + "ata_addresses_missing", + "committed ATA lifecycle projection requires the decoded address contract", + ); + }, + }; + let validation = validate_ata_addresses(operation, addresses); + if let std::result::Result::Err((code, message)) = validation { + return crate::MtApiMaterializerExecutionResult::refused(code, message); + } + let lifecycle_kind = + match ATA_LIFECYCLE_ENTRIES.iter().find(|(entry, _)| return *entry == operation) { + std::option::Option::Some((_, value)) => *value, + std::option::Option::None => { + return crate::MtApiMaterializerExecutionResult::ignored(); + }, + }; + let associated_token_account = if operation == "recover_nested" { + observed_address(addresses, "nestedAssociatedTokenAccount") + } else { + observed_address(addresses, "associatedTokenAccount") + }; + let token_program = addresses + .get("tokenProgram") + .and_then(|value| return value.get("programId")) + .cloned() + .unwrap_or(serde_json::Value::Null); + let wallet = addresses.get("walletOwner").cloned().unwrap_or(serde_json::Value::Null); + let mint = if operation == "recover_nested" { + addresses.get("nestedMint").cloned().unwrap_or(serde_json::Value::Null) + } else { + addresses.get("mint").cloned().unwrap_or(serde_json::Value::Null) + }; + let output = crate::MtApiMaterializedOutput { + output_key: format!("ata_lifecycle:{lifecycle_kind}:0"), + family: crate::MdMaterializedEventFamily::TokenAccount, + payload_json: serde_json::json!({ + "projectionVersion": crate::MT_TOKEN_ACCOUNTS_PROJECTION_VERSION, + "domain": "spl_associated_token_account_lifecycle", + "projectionSemantics": "committed_associated_address_lifecycle_not_token_state_snapshot", + "idempotenceKey": format!( + "ata:{}:{}:{}:{}:{}", + observation.event.signature.0, + observation.event.instruction_path.0, + observation.event.program_id.0, + lifecycle_kind, + associated_token_account.as_str().unwrap_or("") + ), + "operation": operation, + "lifecycleKind": lifecycle_kind, + "associatedTokenAccount": associated_token_account, + "walletOwner": wallet, + "mint": mint, + "tokenProgramId": token_program, + "fundingAccount": addresses.get("fundingAccount").cloned().unwrap_or(serde_json::Value::Null), + "ownerMint": addresses.get("ownerMint").cloned().unwrap_or(serde_json::Value::Null), + "nestedMint": addresses.get("nestedMint").cloned().unwrap_or(serde_json::Value::Null), + "ownerAssociatedTokenAccount": observed_address(addresses, "ownerAssociatedTokenAccount"), + "nestedAssociatedTokenAccount": observed_address(addresses, "nestedAssociatedTokenAccount"), + "walletNestedMintAssociatedTokenAccount": observed_address(addresses, "walletNestedMintAssociatedTokenAccount"), + "idempotentOutcome": if operation == "create_idempotent" { + "created_or_reused_not_distinguishable_from_parent_instruction_alone" + } else { + "not_applicable" + }, + "signature": observation.event.signature.0.clone(), + "slot": observation.event.slot.0, + "instructionPath": observation.event.instruction_path.0.clone(), + "programId": observation.event.program_id.0.clone(), + "committed": true, + "transactionFinalAccountStateCaptured": false, + "tokenBalanceReconstructed": false, + "splTokenCpiMutationsDuplicated": false, + "ownership": { + "ataParent": "associated_address_lifecycle_only", + "splTokenCpi": "initialize_transfer_and_close_mutations" + }, + "provenance": { + "processorName": crate::MT_TOKEN_ACCOUNTS_PROCESSOR_NAME, + "processorVersion": env!("CARGO_PKG_VERSION"), + "sourceSurface": observation.event.surface_code.0.clone(), + "sourceEventCode": observation.event.event_code.0.clone(), + "sourceEventKey": observation.event_key.clone() + } + }), + }; + tracing::debug!( + target: crate::MT_TOKEN_ACCOUNTS_TRACING_TARGET, + action = "materialize_ata_lifecycle", + signature = %observation.event.signature.0, + instruction_path = %observation.event.instruction_path.0, + operation, + lifecycle_kind, + "materialize committed ATA lifecycle without duplicating SPL Token CPI mutations" + ); + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, + outputs: std::vec![output], + diagnostics: std::vec::Vec::new(), + }; +} + +fn validate_ata_addresses( + operation: &str, + addresses: &serde_json::Value, +) -> std::result::Result<(), (&'static str, &'static str)> { + let token_supported = addresses + .get("tokenProgram") + .and_then(|value| return value.get("supported")) + .and_then(serde_json::Value::as_bool) + == std::option::Option::Some(true); + let token_program_id = addresses + .get("tokenProgram") + .and_then(|value| return value.get("programId")) + .and_then(serde_json::Value::as_str); + let token_program_exact = matches!( + token_program_id, + std::option::Option::Some(kb_program_ids::SPL_TOKEN_PROGRAM_ID) + | std::option::Option::Some(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID) + ); + if !token_supported || !token_program_exact { + return std::result::Result::Err(( + "ata_token_program_not_supported", + "ATA lifecycle projection requires classic SPL Token or Token-2022", + )); + } + let fields: &[&str] = if operation == "recover_nested" { + &[ + "ownerAssociatedTokenAccount", + "nestedAssociatedTokenAccount", + "walletNestedMintAssociatedTokenAccount", + ] + } else { + &["associatedTokenAccount"] + }; + for field in fields { + let valid = addresses + .get(*field) + .and_then(|value| return value.get("valid")) + .and_then(serde_json::Value::as_bool) + == std::option::Option::Some(true); + let observed = observed_address(addresses, field); + if !valid || observed.as_str().is_none_or(|value| return value.is_empty()) { + return std::result::Result::Err(( + "ata_derived_address_invalid", + "ATA lifecycle projection requires every canonical address validation to pass", + )); + } + } + let identity_fields: &[&str] = if operation == "recover_nested" { + &["walletOwner", "ownerMint", "nestedMint"] + } else { + &["walletOwner", "mint"] + }; + if identity_fields.iter().any(|field| { + return addresses + .get(*field) + .and_then(serde_json::Value::as_str) + .is_none_or(|value| return value.is_empty()); + }) { + return std::result::Result::Err(( + "ata_identity_field_missing", + "ATA lifecycle projection requires wallet and mint identities", + )); + } + return std::result::Result::Ok(()); +} + +fn observed_address(addresses: &serde_json::Value, field: &str) -> serde_json::Value { + return addresses + .get(field) + .and_then(|value| return value.get("observed")) + .cloned() + .unwrap_or(serde_json::Value::Null); +} + +fn account_key_for_role(accounts: &serde_json::Value, role: &str) -> serde_json::Value { + let value = accounts.as_array().and_then(|rows| { + return rows.iter().find_map(|row| { + if row.get("role").and_then(serde_json::Value::as_str) + != std::option::Option::Some(role) + { + return std::option::Option::None; + } + return row.get("accountKey").and_then(serde_json::Value::as_str); + }); + }); + return match value { + std::option::Option::Some(account_key) => { + serde_json::Value::String(account_key.to_string()) + }, + std::option::Option::None => serde_json::Value::Null, + }; +} + +/// Materialize one already parsed Token-2022 account snapshot without inferring hidden state. +pub fn materialize_token2022_state_snapshot( + account_key: &str, + slot: u64, + state: &crate::DcToken2022State, +) -> std::result::Result { + if account_key.is_empty() { + return std::result::Result::Err( + "Token-2022 state snapshot requires a non-empty account key".to_string(), + ); + } + let kind = match state.kind { + crate::DcToken2022StateKind::Mint => "mint", + crate::DcToken2022StateKind::Account => "account", + crate::DcToken2022StateKind::Multisig => "multisig", + }; + let extensions = state + .extensions + .iter() + .map(|entry| { + return serde_json::json!({ + "extensionType": entry.extension_type, + "extensionName": entry.extension_name, + "valueHex": entry.value_hex, + "valueFields": entry.value_fields, + }); + }) + .collect::>(); + let extension_names = state + .extensions + .iter() + .map(|entry| return entry.extension_name) + .collect::>(); + let contains_confidential_state = state.extensions.iter().any(|entry| { + return entry.extension_name.starts_with("confidential_") + || entry.extension_name == "confidential_mint_burn"; + }); + return std::result::Result::Ok(crate::MtApiMaterializedOutput { + output_key: format!("token2022_state_snapshot:{account_key}:{slot}"), + family: crate::MdMaterializedEventFamily::TokenAccount, + payload_json: serde_json::json!({ + "projectionVersion": crate::MT_TOKEN_ACCOUNTS_PROJECTION_VERSION, + "domain": "spl_token2022_account_state", + "projectionSemantics": "authoritative_bounded_account_snapshot", + "idempotenceKey": format!("token2022_state:{account_key}:{slot}"), + "accountKey": account_key, + "slot": slot, + "programId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "stateKind": kind, + "baseFields": state.base_fields, + "baseHex": state.base_hex, + "accountType": state.account_type, + "extensionCount": state.extensions.len(), + "extensionNames": extension_names, + "extensions": extensions, + "containsConfidentialState": contains_confidential_state, + "confidentialValuesDecrypted": false, + "finalAccountStateCaptured": true, + "provenance": { + "processorName": crate::MT_TOKEN_ACCOUNTS_PROCESSOR_NAME, + "processorVersion": env!("CARGO_PKG_VERSION"), + "source": "bounded_token2022_state_parser" + } + }), + }); +} + +#[cfg(test)] +mod tests { + fn observation( + entry: &str, + family: crate::MdEventFamily, + failed: bool, + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { + event_key: format!("token:{entry}:0"), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("1/0".to_string()), + program_id: crate::MdProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()), + protocol_code: crate::MdProtocolCode("spl_token".to_string()), + surface_code: crate::MdSurfaceCode("spl_token".to_string()), + event_code: crate::MdEventCode(format!("spl_token.{entry}")), + event_name: crate::MdEventName(entry.to_string()), + event_family: family, + source_kind: crate::MdEventSourceKind::InnerInstruction, + confidence: crate::MdDecoderConfidence::ManualExact, + }, + payload_json: serde_json::json!({ + "parameters": {"amountRaw":"18446744073709551615","decimals":9}, + "accounts": [{"role":"mint","accountKey":"mint111"}], + "authority": {"form":"single"} + }), + transaction_failed: failed, + transaction_error: if failed { + std::option::Option::Some(serde_json::json!({"error":"failed"})) + } else { + std::option::Option::None + }, + observation_committed: !failed, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, + evidence: std::vec!["fixture".to_string()], + }, + }; + } + + fn token2022_observation( + entry: &str, + family: crate::MdEventFamily, + failed: bool, + ) -> crate::DcApiDecodedObservation { + let mut observation = observation(entry, family, failed); + observation.event.program_id = + crate::MdProgramId(kb_program_ids::SPL_TOKEN2022_PROGRAM_ID.to_string()); + observation.event.protocol_code = crate::MdProtocolCode("spl_token2022".to_string()); + observation.event.surface_code = crate::MdSurfaceCode("spl_token2022".to_string()); + observation.event.event_code = crate::MdEventCode(format!("spl_token2022.{entry}")); + observation.event_key = format!("token2022:{entry}:0"); + return observation; + } + + fn ata_observation(entry: &str, failed: bool, valid: bool) -> crate::DcApiDecodedObservation { + let addresses = if entry == "recover_nested" { + serde_json::json!({ + "tokenProgram": { + "programId": kb_program_ids::SPL_TOKEN_PROGRAM_ID, + "kind": "spl_token_classic", + "supported": true + }, + "ownerAssociatedTokenAccount": {"expected":"ownerAta","observed":"ownerAta","valid":valid}, + "nestedAssociatedTokenAccount": {"expected":"nestedAta","observed":"nestedAta","valid":valid}, + "walletNestedMintAssociatedTokenAccount": {"expected":"destinationAta","observed":"destinationAta","valid":valid}, + "walletOwner": "wallet111", + "ownerMint": "ownerMint111", + "nestedMint": "nestedMint111" + }) + } else { + serde_json::json!({ + "tokenProgram": { + "programId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + "kind": "token2022", + "supported": true + }, + "associatedTokenAccount": {"expected":"ata111","observed":"ata111","valid":valid}, + "fundingAccount": "payer111", + "walletOwner": "wallet111", + "mint": "mint111" + }) + }; + return crate::DcApiDecodedObservation { + event_key: format!("ata:{entry}:0"), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("0".to_string()), + program_id: crate::MdProgramId( + kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string(), + ), + protocol_code: crate::MdProtocolCode("spl_associated_token_account".to_string()), + surface_code: crate::MdSurfaceCode("spl_associated_token_account".to_string()), + event_code: crate::MdEventCode(format!("spl_associated_token_account.{entry}")), + event_name: crate::MdEventName(entry.to_string()), + event_family: crate::MdEventFamily::Lifecycle, + source_kind: crate::MdEventSourceKind::Instruction, + confidence: crate::MdDecoderConfidence::ManualExact, + }, + payload_json: serde_json::json!({"addresses":addresses}), + transaction_failed: failed, + transaction_error: std::option::Option::None, + observation_committed: !failed, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, + evidence: std::vec!["fixture".to_string()], + }, + }; + } + + #[test] + fn committed_checked_transfer_preserves_exact_amount_mint_and_path() { + let observation = + observation("transfer_checked", crate::MdEventFamily::TokenAccount, false); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs[0].payload_json["amountRaw"], "18446744073709551615"); + assert_eq!(result.outputs[0].payload_json["mint"], "mint111"); + assert_eq!(result.outputs[0].payload_json["instructionPath"], "1/0"); + assert_eq!(result.outputs[0].payload_json["transactionFinalAccountStateCaptured"], false); + } + + #[test] + fn committed_token2022_transfer_has_the_same_single_projection_owner() { + let observation = + token2022_observation("transfer_checked", crate::MdEventFamily::TokenAccount, false); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs.len(), 1); + assert_eq!(result.outputs[0].payload_json["operation"], "transfer_checked"); + assert_eq!( + result.outputs[0].payload_json["programId"], + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID + ); + } + + #[test] + fn failed_mutation_is_refused() { + let observation = observation("burn", crate::MdEventFamily::TokenBurn, true); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); + assert!(result.outputs.is_empty()); + } + + #[test] + fn batch_parent_admin_and_conversion_events_are_not_duplicated() { + for (entry, family) in [ + ("batch", crate::MdEventFamily::Audit), + ("set_authority", crate::MdEventFamily::Admin), + ("amount_to_ui_amount", crate::MdEventFamily::Audit), + ] { + let observation = observation(entry, family, false); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); + } + } + + #[test] + fn every_ata_variant_has_one_exact_lifecycle_projection() { + for (entry, expected_kind, expected_ata, expected_token_program) in [ + ("create", "ata_created", "ata111", kb_program_ids::SPL_TOKEN2022_PROGRAM_ID), + ( + "create_idempotent", + "ata_created_or_reused_idempotently", + "ata111", + kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, + ), + ( + "recover_nested", + "nested_ata_recovered", + "nestedAta", + kb_program_ids::SPL_TOKEN_PROGRAM_ID, + ), + ] { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &ata_observation(entry, false, true), + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(result.outputs.len(), 1); + assert_eq!(result.outputs[0].payload_json["lifecycleKind"], expected_kind); + assert_eq!(result.outputs[0].payload_json["associatedTokenAccount"], expected_ata); + assert_eq!(result.outputs[0].payload_json["tokenProgramId"], expected_token_program); + assert_eq!(result.outputs[0].payload_json["tokenBalanceReconstructed"], false); + assert_eq!(result.outputs[0].payload_json["splTokenCpiMutationsDuplicated"], false); + } + } + + #[test] + fn idempotent_parent_does_not_invent_created_or_reused_branch() { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &ata_observation("create_idempotent", false, true), + ); + assert_eq!( + result.outputs[0].payload_json["idempotentOutcome"], + "created_or_reused_not_distinguishable_from_parent_instruction_alone" + ); + assert!(result.outputs[0].payload_json.get("reused").is_none()); + assert!(result.outputs[0].payload_json.get("created").is_none()); + } + + #[test] + fn uncommitted_or_invalid_ata_lifecycle_is_refused() { + for observation in [ + ata_observation("create", true, true), + ata_observation("recover_nested", false, false), + ] { + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); + assert!(result.outputs.is_empty()); + } + } + + #[test] + fn ata_parent_and_classic_token_cpi_children_own_distinct_facts() { + let parent = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &ata_observation("recover_nested", false, true), + ); + let transfer = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation("transfer", crate::MdEventFamily::TokenAccount, false), + ); + let close = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation("close_account", crate::MdEventFamily::TokenAccount, false), + ); + assert_eq!(parent.outputs[0].payload_json["lifecycleKind"], "nested_ata_recovered"); + assert_eq!( + parent.outputs[0].payload_json["ownership"]["ataParent"], + "associated_address_lifecycle_only" + ); + assert!(parent.outputs[0].payload_json.get("amountRaw").is_none()); + assert_eq!(transfer.outputs[0].payload_json["operation"], "transfer"); + assert_eq!(close.outputs[0].payload_json["operation"], "close_account"); + assert_eq!(transfer.outputs[0].payload_json["domain"], "spl_token_account_mutation"); + assert_eq!(close.outputs[0].payload_json["domain"], "spl_token_account_mutation"); + } + + #[test] + fn ata_matrix_and_compiled_token_account_projection_ownership_are_equal() { + let matrix: serde_json::Value = match serde_json::from_str(include_str!( + "../../../../docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json" + )) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("ATA matrix is invalid: {error}"), + }; + let instructions = match matrix.get("instructions").and_then(serde_json::Value::as_array) { + std::option::Option::Some(value) => value, + std::option::Option::None => panic!("ATA matrix instructions are absent"), + }; + for (entry, fact) in super::ATA_LIFECYCLE_ENTRIES { + let row = match instructions.iter().find(|row| { + return row.get("name").and_then(serde_json::Value::as_str) + == std::option::Option::Some(*entry); + }) { + std::option::Option::Some(value) => value, + std::option::Option::None => panic!("ATA matrix entry {entry} is absent"), + }; + let expected = format!("token_accounts:{fact}"); + assert!(row["authorizedProjections"].as_array().is_some_and(|values| { + return values.iter().any(|value| return value == expected.as_str()); + })); + } + let owner = &matrix["materializationContract"]["projectionOwners"][0]; + let matrix_facts = match owner["facts"].as_array() { + std::option::Option::Some(values) => values + .iter() + .filter_map(|value| return value.as_str()) + .collect::>(), + std::option::Option::None => panic!("ATA token-account owner facts are absent"), + }; + let compiled_facts = super::ATA_LIFECYCLE_ENTRIES + .iter() + .map(|(_, fact)| return *fact) + .collect::>(); + assert_eq!(matrix_facts, compiled_facts); + } + + #[test] + fn second_ata_materialization_is_byte_for_byte_idempotent() { + let observation = ata_observation("create_idempotent", false, true); + let first = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation, + ); + let second = crate::MtApiEventMaterializer::materialize( + &crate::MtTokenAccountsMaterializer, + &observation, + ); + assert_eq!(first, second); + assert_eq!(first.outputs[0].output_key, second.outputs[0].output_key); + assert_eq!( + first.outputs[0].payload_json["idempotenceKey"], + second.outputs[0].payload_json["idempotenceKey"] + ); + } + + #[test] + fn token2022_state_snapshot_preserves_base_and_ordered_extensions() { + let state = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Mint, + base_fields: serde_json::json!({"supply":"42","decimals":9,"initialized":true}), + base_hex: "00".repeat(82), + account_type: std::option::Option::Some(1), + extensions: std::vec![ + crate::DcToken2022TlvEntry { + extension_type: 1, + extension_name: "transfer_fee_config", + value_hex: "11".repeat(108), + value_fields: serde_json::json!({"withheldAmount":"7"}), + }, + crate::DcToken2022TlvEntry { + extension_type: 4, + extension_name: "confidential_transfer_mint", + value_hex: "22".repeat(65), + value_fields: serde_json::json!({"autoApproveNewAccounts":true}), + }, + ], + }; + let output = match crate::materialize_token2022_state_snapshot("mint111", 99, &state) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("snapshot failed: {error}"), + }; + assert_eq!(output.payload_json["stateKind"], "mint"); + assert_eq!(output.payload_json["extensionCount"], 2); + assert_eq!(output.payload_json["extensionNames"][0], "transfer_fee_config"); + assert_eq!(output.payload_json["extensionNames"][1], "confidential_transfer_mint"); + assert_eq!(output.payload_json["containsConfidentialState"], true); + assert_eq!(output.payload_json["confidentialValuesDecrypted"], false); + assert_eq!(output.payload_json["baseFields"]["supply"], "42"); + } + + #[test] + fn token2022_state_snapshot_is_idempotent_and_rejects_missing_identity() { + let state = crate::DcToken2022State { + kind: crate::DcToken2022StateKind::Account, + base_fields: serde_json::json!({"mint":"mint111","owner":"wallet111","amount":"5"}), + base_hex: "00".repeat(165), + account_type: std::option::Option::None, + extensions: std::vec::Vec::new(), + }; + let first = crate::materialize_token2022_state_snapshot("account111", 7, &state); + let second = crate::materialize_token2022_state_snapshot("account111", 7, &state); + assert_eq!(first, second); + assert!(crate::materialize_token2022_state_snapshot("", 7, &state).is_err()); + } +} diff --git a/kb-lib/src/materializer/token/constants.rs b/kb-lib/src/materializer/token/constants.rs new file mode 100644 index 0000000..495381c --- /dev/null +++ b/kb-lib/src/materializer/token/constants.rs @@ -0,0 +1,11 @@ +// file: kb-lib/src/materializer/token/constants.rs +// version: 1 + +//! Local constants for classic SPL Token account projections. + +/// Stable processor name persisted by the replay ledger. +pub(crate) const MT_TOKEN_ACCOUNTS_PROCESSOR_NAME: &str = "spl_token_accounts"; +/// Stable projection payload contract version. +pub(crate) const MT_TOKEN_ACCOUNTS_PROJECTION_VERSION: u32 = 3; +/// Canonical tracing target for this component. +pub(crate) const MT_TOKEN_ACCOUNTS_TRACING_TARGET: &str = "kb-lib.materializer.token"; diff --git a/kb-lib/src/materializer/token/metadata_risk.rs b/kb-lib/src/materializer/token/metadata_risk.rs index 39d4ccf..e6a0278 100644 --- a/kb-lib/src/materializer/token/metadata_risk.rs +++ b/kb-lib/src/materializer/token/metadata_risk.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/token/metadata_risk.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_token_metadata_risk`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_token_metadata_risk"; +const LEGACY_CRATE: &str = "kb_materializer_token_metadata_risk"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/trades.rs b/kb-lib/src/materializer/trades.rs index 6998d41..bff5e48 100644 --- a/kb-lib/src/materializer/trades.rs +++ b/kb-lib/src/materializer/trades.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/trades.rs -// version: 1 +// version: 2 //! `trades` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/trades/core.rs b/kb-lib/src/materializer/trades/core.rs index bfe58ad..06a8f4d 100644 --- a/kb-lib/src/materializer/trades/core.rs +++ b/kb-lib/src/materializer/trades/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/trades/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_trades`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_trades"; +const LEGACY_CRATE: &str = "kb_materializer_trades"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/materializer/transaction.rs b/kb-lib/src/materializer/transaction.rs index 53e79e6..4f9831d 100644 --- a/kb-lib/src/materializer/transaction.rs +++ b/kb-lib/src/materializer/transaction.rs @@ -1,6 +1,19 @@ // file: kb-lib/src/materializer/transaction.rs -// version: 1 +// version: 2 //! `transaction` materializer family. -pub mod annotations; +mod annotations; +mod constants; + +/// Maximum Memo payload accepted by transaction annotations. +pub(crate) use self::constants::MT_TRANSACTION_ANNOTATIONS_MAX_MEMO_PAYLOAD_BYTES; +/// Stable processor name for transaction annotations. +pub(crate) use self::constants::MT_TRANSACTION_ANNOTATIONS_PROCESSOR_NAME; +/// Stable projection contract version for transaction annotations. +pub(crate) use self::constants::MT_TRANSACTION_ANNOTATIONS_PROJECTION_VERSION; +/// Canonical tracing target for transaction annotations. +pub(crate) use self::constants::MT_TRANSACTION_ANNOTATIONS_TRACING_TARGET; + +/// Stable committed Memo transaction annotation materializer. +pub use self::annotations::MtTransactionAnnotationMaterializer; diff --git a/kb-lib/src/materializer/transaction/annotations.rs b/kb-lib/src/materializer/transaction/annotations.rs index 5e66581..6be4ada 100644 --- a/kb-lib/src/materializer/transaction/annotations.rs +++ b/kb-lib/src/materializer/transaction/annotations.rs @@ -1,10 +1,614 @@ // file: kb-lib/src/materializer/transaction/annotations.rs -// version: 1 +// version: 2 -//! Migration boundary for legacy crate `kb_materializer_transaction_annotations`. +//! Exact committed SPL Memo transaction annotation projection. -/// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_transaction_annotations"; +const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[crate::MdEventFamily::Audit]; +const MEMO_ENTRY_NAMES: &[&str] = &["add_memo", "memo_intent", "invalid_memo_attempt"]; -/// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum MemoGeneration { + V1, + V3, + V4, +} + +impl MemoGeneration { + fn from_event(event: &crate::MdDecodedProtocolEvent) -> std::option::Option { + if event.program_id.0 == kb_program_ids::SPL_MEMO_V1_PROGRAM_ID + && event.surface_code.0 == "spl_memo_v1" + { + return std::option::Option::Some(Self::V1); + } + if event.program_id.0 == kb_program_ids::SPL_MEMO_V3_PROGRAM_ID + && event.surface_code.0 == "spl_memo_v3" + { + return std::option::Option::Some(Self::V3); + } + if event.program_id.0 == kb_program_ids::SPL_MEMO_V4_PROGRAM_ID + && event.surface_code.0 == "spl_memo_v4" + { + return std::option::Option::Some(Self::V4); + } + return std::option::Option::None; + } + + fn code(self) -> &'static str { + return match self { + Self::V1 => "v1", + Self::V3 => "v3", + Self::V4 => "v4", + }; + } + + fn signer_status(self) -> &'static str { + return match self { + Self::V1 => "not_applicable", + Self::V3 | Self::V4 => "valid", + }; + } +} + +struct MemoProjection { + generation: MemoGeneration, + memo_text: std::string::String, + payload_length_bytes: u64, + payload_sha256: std::string::String, + required_signers: std::vec::Vec, + observed_signers: std::vec::Vec, + verified_signers: std::vec::Vec, + signer_validation_status: std::string::String, +} + +/// Stable transaction annotation materializer. +#[derive(Clone, Debug, Default)] +pub struct MtTransactionAnnotationMaterializer; + +impl crate::MtMaterializer for crate::MtTransactionAnnotationMaterializer { + fn materializer_name(&self) -> &'static str { + return "kb_materializer_transaction_annotations"; + } + + fn materializer_version(&self) -> &'static str { + return env!("CARGO_PKG_VERSION"); + } + + fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { + return accepts_event(event); + } + + fn materialize_event( + &self, + _event: &crate::MdDecodedProtocolEvent, + ) -> kb_core::Result> { + return std::result::Result::Ok(std::vec::Vec::new()); + } +} + +impl crate::MtApiEventMaterializer for crate::MtTransactionAnnotationMaterializer { + fn identity(&self) -> crate::MtApiMaterializerIdentity { + return crate::MtApiMaterializerIdentity { + name: crate::MT_TRANSACTION_ANNOTATIONS_PROCESSOR_NAME.to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + }; + } + + fn accepted_families(&self) -> &'static [crate::MdEventFamily] { + return ACCEPTED_FAMILIES; + } + + fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { + return accepts_event(&observation.event); + } + + fn transaction_policy( + &self, + _family: crate::MdEventFamily, + ) -> crate::MtApiMaterializationTransactionPolicy { + return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; + } + + fn materialize( + &self, + observation: &crate::DcApiDecodedObservation, + ) -> crate::MtApiMaterializerExecutionResult { + if !accepts_event(&observation.event) { + return crate::MtApiMaterializerExecutionResult::ignored(); + } + if observation.transaction_failed || !observation.observation_committed { + return crate::MtApiMaterializerExecutionResult::refused( + "uncommitted_transaction_annotation_refused", + "failed or uncommitted Memo observations cannot create transaction annotations", + ); + } + if observation.event.event_name.0 != "add_memo" { + return crate::MtApiMaterializerExecutionResult::refused( + "invalid_transaction_annotation_source_refused", + "only a committed add_memo observation can create a transaction annotation", + ); + } + let projection_result = parse_projection(observation); + let projection = match projection_result { + std::result::Result::Ok(value) => value, + std::result::Result::Err(message) => { + return failed("memo_annotation_payload_invalid", message); + }, + }; + let idempotence_key = format!( + "spl_memo:{}:{}:{}:{}", + observation.event.signature.0, + observation.event.instruction_path.0, + observation.event.program_id.0, + projection.payload_sha256 + ); + let output = crate::MtApiMaterializedOutput { + output_key: "transaction_annotation:spl_memo:0".to_string(), + family: crate::MdMaterializedEventFamily::TransactionAnnotation, + payload_json: serde_json::json!({ + "projectionVersion": crate::MT_TRANSACTION_ANNOTATIONS_PROJECTION_VERSION, + "domain": "transaction_annotation", + "annotationKind": "spl_memo", + "idempotenceKey": idempotence_key, + "signature": observation.event.signature.0.clone(), + "slot": observation.event.slot.0, + "instructionPath": observation.event.instruction_path.0.clone(), + "sourceKind": match observation.event.source_kind { + crate::MdEventSourceKind::InnerInstruction => "inner_instruction", + _ => "instruction" + }, + "generation": projection.generation.code(), + "programId": observation.event.program_id.0.clone(), + "text": projection.memo_text, + "payloadLengthBytes": projection.payload_length_bytes, + "payloadSha256": projection.payload_sha256, + "signers": { + "validationStatus": projection.signer_validation_status, + "required": projection.required_signers, + "observed": projection.observed_signers, + "verified": projection.verified_signers + }, + "committed": true, + "provenance": { + "processorName": crate::MT_TRANSACTION_ANNOTATIONS_PROCESSOR_NAME, + "processorVersion": env!("CARGO_PKG_VERSION"), + "sourceProtocol": observation.event.protocol_code.0.clone(), + "sourceSurface": observation.event.surface_code.0.clone(), + "sourceEventCode": observation.event.event_code.0.clone(), + "sourceEventKey": observation.event_key.clone() + } + }), + }; + tracing::debug!( + target: crate::MT_TRANSACTION_ANNOTATIONS_TRACING_TARGET, + action = "materialize_transaction_annotation", + signature = %observation.event.signature.0, + instruction_path = %observation.event.instruction_path.0, + program_id = %observation.event.program_id.0, + generation = projection.generation.code(), + payload_length_bytes = projection.payload_length_bytes, + output_count = 1_usize, + "materialize committed SPL Memo transaction annotation" + ); + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Inserted, + outputs: std::vec![output], + diagnostics: std::vec::Vec::new(), + }; + } +} + +fn accepts_event(event: &crate::MdDecodedProtocolEvent) -> bool { + return event.event_family == crate::MdEventFamily::Audit + && event.protocol_code.0 == "spl_memo" + && (event.source_kind == crate::MdEventSourceKind::Instruction + || event.source_kind == crate::MdEventSourceKind::InnerInstruction) + && MemoGeneration::from_event(event).is_some() + && MEMO_ENTRY_NAMES.contains(&event.event_name.0.as_str()); +} + +fn parse_projection( + observation: &crate::DcApiDecodedObservation, +) -> std::result::Result { + let generation = match MemoGeneration::from_event(&observation.event) { + std::option::Option::Some(value) => value, + std::option::Option::None => { + return std::result::Result::Err( + "Memo generation and Program ID do not match".to_string(), + ); + }, + }; + let payload = &observation.payload_json; + if payload.get("committed").and_then(serde_json::Value::as_bool) + != std::option::Option::Some(true) + { + return std::result::Result::Err("Memo payload is not marked committed".to_string()); + } + if payload.get("transactionSucceeded").and_then(serde_json::Value::as_bool) + != std::option::Option::Some(true) + || payload.get("payloadComplete").and_then(serde_json::Value::as_bool) + != std::option::Option::Some(true) + || string_field(payload, "runtimeValidation") + != std::option::Option::Some("proven_by_successful_transaction") + || payload + .get("utf8Validation") + .and_then(|value| return string_field(value, "status")) + != std::option::Option::Some("valid") + { + return std::result::Result::Err( + "Memo successful runtime validation proof is incomplete".to_string(), + ); + } + if string_field(payload, "generation") != std::option::Option::Some(generation.code()) { + return std::result::Result::Err( + "Memo payload generation does not match its surface".to_string(), + ); + } + if string_field(payload, "programId") + != std::option::Option::Some(observation.event.program_id.0.as_str()) + { + return std::result::Result::Err( + "Memo payload Program ID does not match its event".to_string(), + ); + } + if string_field(payload, "instructionPath") + != std::option::Option::Some(observation.event.instruction_path.0.as_str()) + { + return std::result::Result::Err( + "Memo payload instruction path does not match its event".to_string(), + ); + } + let memo_text = match string_field(payload, "memoText") { + std::option::Option::Some(value) => value.to_string(), + std::option::Option::None => { + return std::result::Result::Err("committed Memo has no UTF-8 text".to_string()); + }, + }; + let payload_length_bytes = + match payload.get("payloadLengthBytes").and_then(serde_json::Value::as_u64) { + std::option::Option::Some(value) => value, + std::option::Option::None => { + return std::result::Result::Err("committed Memo has no byte length".to_string()); + }, + }; + let measured_length = match u64::try_from(memo_text.len()) { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => { + return std::result::Result::Err(format!( + "Memo text length conversion failed: {error}" + )); + }, + }; + if measured_length != payload_length_bytes { + return std::result::Result::Err( + "Memo byte length does not match its UTF-8 text".to_string(), + ); + } + if payload_length_bytes > crate::MT_TRANSACTION_ANNOTATIONS_MAX_MEMO_PAYLOAD_BYTES { + return std::result::Result::Err( + "Memo byte length exceeds the projection limit".to_string(), + ); + } + let payload_sha256 = match string_field(payload, "payloadSha256") { + std::option::Option::Some(value) if is_sha256(value) => value.to_string(), + _ => return std::result::Result::Err("Memo payload SHA-256 is invalid".to_string()), + }; + let signer_validation = match payload.get("signerValidation") { + std::option::Option::Some(value) => value, + std::option::Option::None => { + return std::result::Result::Err("Memo signer validation is absent".to_string()); + }, + }; + let signer_validation_status = match string_field(signer_validation, "status") { + std::option::Option::Some(value) if value == generation.signer_status() => { + value.to_string() + }, + _ => { + return std::result::Result::Err( + "Memo signer validation status is inconsistent".to_string(), + ); + }, + }; + let missing_signers = match string_array(signer_validation, "missingRequiredSigners") { + std::result::Result::Ok(value) => value, + std::result::Result::Err(message) => return std::result::Result::Err(message), + }; + if !missing_signers.is_empty() { + return std::result::Result::Err("committed Memo reports missing signers".to_string()); + } + let required_signers = match string_array(signer_validation, "orderedRequiredSigners") { + std::result::Result::Ok(value) => value, + std::result::Result::Err(message) => return std::result::Result::Err(message), + }; + let observed_signers = match string_array(signer_validation, "orderedObservedSigners") { + std::result::Result::Ok(value) => value, + std::result::Result::Err(message) => return std::result::Result::Err(message), + }; + let verified_signers = if generation == MemoGeneration::V1 { + if !required_signers.is_empty() { + return std::result::Result::Err("Memo v1 cannot require signers".to_string()); + } + std::vec::Vec::new() + } else { + if required_signers != observed_signers { + return std::result::Result::Err( + "committed Memo required and observed signers differ".to_string(), + ); + } + observed_signers.clone() + }; + return std::result::Result::Ok(MemoProjection { + generation, + memo_text, + payload_length_bytes, + payload_sha256, + required_signers, + observed_signers, + verified_signers, + signer_validation_status, + }); +} + +fn string_field<'a>(value: &'a serde_json::Value, key: &str) -> std::option::Option<&'a str> { + return value.get(key).and_then(serde_json::Value::as_str); +} + +fn string_array( + value: &serde_json::Value, + key: &str, +) -> std::result::Result, std::string::String> { + let values = match value.get(key).and_then(serde_json::Value::as_array) { + std::option::Option::Some(values) => values, + std::option::Option::None => { + return std::result::Result::Err(format!("Memo signer field {key} is not an array")); + }, + }; + let mut output = std::vec::Vec::with_capacity(values.len()); + for item in values { + let text = match item.as_str() { + std::option::Option::Some(text) if !text.trim().is_empty() => text, + _ => { + return std::result::Result::Err(format!( + "Memo signer field {key} contains an invalid pubkey" + )); + }, + }; + output.push(text.to_string()); + } + return std::result::Result::Ok(output); +} + +fn is_sha256(value: &str) -> bool { + return value.len() == 64 + && value + .as_bytes() + .iter() + .all(|byte| return byte.is_ascii_hexdigit() && !byte.is_ascii_uppercase()); +} + +fn failed(code: &str, message: std::string::String) -> crate::MtApiMaterializerExecutionResult { + return crate::MtApiMaterializerExecutionResult { + status: crate::MtApiMaterializerOutcomeStatus::Failed, + outputs: std::vec::Vec::new(), + diagnostics: std::vec![crate::MtApiMaterializerDiagnostic { + code: code.to_string(), + message, + retriable: false, + }], + }; +} + +#[cfg(test)] +mod tests { + fn observation( + program_id: &str, + surface_code: &str, + generation: &str, + event_name: &str, + failed: bool, + committed: bool, + required_signers: serde_json::Value, + observed_signers: serde_json::Value, + ) -> crate::DcApiDecodedObservation { + return crate::DcApiDecodedObservation { + event_key: "memo:0".to_string(), + event: crate::MdDecodedProtocolEvent { + signature: crate::MdSignature("signature".to_string()), + slot: crate::MdSlot(42), + instruction_path: crate::MdInstructionPath("1/0".to_string()), + program_id: crate::MdProgramId(program_id.to_string()), + protocol_code: crate::MdProtocolCode("spl_memo".to_string()), + surface_code: crate::MdSurfaceCode(surface_code.to_string()), + event_code: crate::MdEventCode(format!("{surface_code}.{event_name}")), + event_name: crate::MdEventName(event_name.to_string()), + event_family: crate::MdEventFamily::Audit, + source_kind: crate::MdEventSourceKind::InnerInstruction, + confidence: crate::MdDecoderConfidence::ManualExact, + }, + payload_json: serde_json::json!({ + "generation": generation, + "programId": program_id, + "instructionPath": "1/0", + "transactionSucceeded": !failed, + "committed": committed, + "memoText": "memo", + "payloadLengthBytes": 4, + "payloadSha256": "1111111111111111111111111111111111111111111111111111111111111111", + "payloadComplete": true, + "utf8Validation": {"status":"valid","invalidFromByte":null}, + "signerValidation": { + "status": if generation == "v1" { "not_applicable" } else { "valid" }, + "orderedRequiredSigners": required_signers, + "orderedObservedSigners": observed_signers, + "missingRequiredSigners": [] + }, + "runtimeValidation": if failed { + "not_proven_transaction_failed" + } else { + "proven_by_successful_transaction" + } + }), + transaction_failed: failed, + transaction_error: if failed { + std::option::Option::Some(serde_json::json!({"InstructionError":[0,"Custom"]})) + } else { + std::option::Option::None + }, + observation_committed: committed, + proof: crate::DcApiDecoderProof { + kind: crate::DcApiDecoderProofKind::Manual, + confidence: crate::MdDecoderConfidence::ManualExact, + evidence: std::vec!["memo".to_string()], + }, + }; + } + + fn v4() -> crate::DcApiDecodedObservation { + return observation( + kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, + "spl_memo_v4", + "v4", + "add_memo", + false, + true, + serde_json::json!(["signer", "signer"]), + serde_json::json!(["signer", "signer"]), + ); + } + + #[test] + fn committed_v4_memo_becomes_deterministic_transaction_annotation() { + let materializer = crate::MtTransactionAnnotationMaterializer; + let first = crate::MtApiEventMaterializer::materialize(&materializer, &v4()); + let second = crate::MtApiEventMaterializer::materialize(&materializer, &v4()); + assert_eq!(first, second); + assert_eq!(first.status, crate::MtApiMaterializerOutcomeStatus::Inserted); + assert_eq!(first.outputs.len(), 1); + assert_eq!( + first.outputs[0].family, + crate::MdMaterializedEventFamily::TransactionAnnotation + ); + assert_eq!( + first.outputs[0].payload_json["signers"]["verified"], + serde_json::json!(["signer", "signer"]) + ); + assert_eq!(first.outputs[0].payload_json["committed"], true); + assert!(first.validate().is_ok()); + } + + #[test] + fn exact_v1_v3_and_v4_surfaces_are_accepted() { + for (program_id, surface, generation) in [ + (kb_program_ids::SPL_MEMO_V1_PROGRAM_ID, "spl_memo_v1", "v1"), + (kb_program_ids::SPL_MEMO_V3_PROGRAM_ID, "spl_memo_v3", "v3"), + (kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, "spl_memo_v4", "v4"), + ] { + let observation = observation( + program_id, + surface, + generation, + "add_memo", + false, + true, + serde_json::json!([]), + serde_json::json!([]), + ); + assert!(crate::MtApiEventMaterializer::accepts_observation( + &crate::MtTransactionAnnotationMaterializer, + &observation, + )); + } + } + + #[test] + fn v1_observed_accounts_are_not_claimed_as_runtime_verified() { + let observation = observation( + kb_program_ids::SPL_MEMO_V1_PROGRAM_ID, + "spl_memo_v1", + "v1", + "add_memo", + false, + true, + serde_json::json!([]), + serde_json::json!(["observed_only"]), + ); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTransactionAnnotationMaterializer, + &observation, + ); + assert_eq!(result.outputs[0].payload_json["signers"]["verified"], serde_json::json!([])); + assert_eq!( + result.outputs[0].payload_json["signers"]["observed"], + serde_json::json!(["observed_only"]) + ); + } + + #[test] + fn failed_or_uncommitted_memo_is_refused_without_output() { + let observation = observation( + kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, + "spl_memo_v4", + "v4", + "memo_intent", + true, + false, + serde_json::json!([]), + serde_json::json!([]), + ); + let materializer = crate::MtTransactionAnnotationMaterializer; + let policy = + crate::materializer_api_validate_materialization_policy(&materializer, &observation); + assert!(policy.is_err()); + let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); + assert!(result.outputs.is_empty()); + } + + #[test] + fn malformed_committed_payload_fails_closed() { + let mut observation = v4(); + observation.payload_json["payloadSha256"] = serde_json::Value::String("bad".to_string()); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTransactionAnnotationMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Failed); + assert!(result.outputs.is_empty()); + assert_eq!(result.diagnostics[0].code, "memo_annotation_payload_invalid"); + } + + #[test] + fn foreign_audit_observation_is_not_accepted() { + let mut observation = v4(); + observation.event.protocol_code = crate::MdProtocolCode("foreign".to_string()); + assert!(!crate::MtApiEventMaterializer::accepts_observation( + &crate::MtTransactionAnnotationMaterializer, + &observation, + )); + let result = crate::MtApiEventMaterializer::materialize( + &crate::MtTransactionAnnotationMaterializer, + &observation, + ); + assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored); + } + + #[test] + fn machine_readable_matrix_declares_transaction_annotation_policy() { + let parsed = serde_json::from_str::(include_str!( + "../../../../docs/SPL_MEMO_MATRIX.json" + )); + let matrix = match parsed { + std::result::Result::Ok(value) => value, + std::result::Result::Err(error) => panic!("memo matrix is invalid JSON: {error}"), + }; + assert_eq!(matrix["matrixVersion"], 4); + assert_eq!( + matrix["materializationContract"]["crate"], + "kb_materializer_transaction_annotations" + ); + assert_eq!( + matrix["materializationContract"]["transactionPolicy"], + "SuccessfulCommittedOnly" + ); + assert_eq!(matrix["materializationContract"]["failedOrUncommittedOutput"], false); + } +} diff --git a/kb-lib/src/materializer/transaction/constants.rs b/kb-lib/src/materializer/transaction/constants.rs new file mode 100644 index 0000000..cd8db32 --- /dev/null +++ b/kb-lib/src/materializer/transaction/constants.rs @@ -0,0 +1,14 @@ +// file: kb-lib/src/materializer/transaction/constants.rs +// version: 1 + +//! Local constants for the transaction annotation materializer. + +/// Maximum Memo payload accepted from the decoded contract. +pub(crate) const MT_TRANSACTION_ANNOTATIONS_MAX_MEMO_PAYLOAD_BYTES: u64 = 4_096; +/// Stable materializer processor name. +pub(crate) const MT_TRANSACTION_ANNOTATIONS_PROCESSOR_NAME: &str = "transaction_annotations"; +/// Stable projection contract version. +pub(crate) const MT_TRANSACTION_ANNOTATIONS_PROJECTION_VERSION: u32 = 1; +/// Canonical tracing target for this component. +pub(crate) const MT_TRANSACTION_ANNOTATIONS_TRACING_TARGET: &str = + "kb-lib.materializer.transaction"; diff --git a/kb-lib/src/materializer/vault.rs b/kb-lib/src/materializer/vault.rs index d95e9f1..b8347ef 100644 --- a/kb-lib/src/materializer/vault.rs +++ b/kb-lib/src/materializer/vault.rs @@ -1,6 +1,6 @@ // file: kb-lib/src/materializer/vault.rs -// version: 1 +// version: 2 //! `vault` materializer family. -pub mod core; +mod core; diff --git a/kb-lib/src/materializer/vault/core.rs b/kb-lib/src/materializer/vault/core.rs index d265c09..e2f296c 100644 --- a/kb-lib/src/materializer/vault/core.rs +++ b/kb-lib/src/materializer/vault/core.rs @@ -1,10 +1,10 @@ // file: kb-lib/src/materializer/vault/core.rs -// version: 1 +// version: 2 //! Migration boundary for legacy crate `kb_materializer_vault`. /// Legacy crate name retained for migration and compatibility tracking. -pub const LEGACY_CRATE: &str = "kb_materializer_vault"; +const LEGACY_CRATE: &str = "kb_materializer_vault"; /// Current porting status. -pub const MIGRATION_STATUS: &str = "source-preserved-pending-port"; +const MIGRATION_STATUS: &str = "source-preserved-pending-port"; diff --git a/kb-lib/src/model.rs b/kb-lib/src/model.rs index 2e100c1..d917462 100644 --- a/kb-lib/src/model.rs +++ b/kb-lib/src/model.rs @@ -3,79 +3,79 @@ //! Shared canonical models consolidated from `kb_model`. -pub mod canonical_transaction; -pub mod decoded; -pub mod materialized; -pub mod nomenclature; -pub mod observation; -pub mod solana; +mod canonical_transaction; +mod decoded; +mod materialized; +mod nomenclature; +mod observation; +/// Source-neutral replay contracts. +mod replay; +mod solana; /// Current canonical transaction document version. -pub use crate::model::canonical_transaction::CANONICAL_TRANSACTION_FORMAT_VERSION; +pub use self::canonical_transaction::MD_CANONICAL_TRANSACTION_FORMAT_VERSION; /// Canonical address lookup table reference. -pub use crate::model::canonical_transaction::CanonicalAddressTableLookup; +pub use self::canonical_transaction::MdCanonicalAddressTableLookup; /// Canonical compiled Solana instruction. -pub use crate::model::canonical_transaction::CanonicalCompiledInstruction; +pub use self::canonical_transaction::MdCanonicalCompiledInstruction; /// Canonical group of inner instructions. -pub use crate::model::canonical_transaction::CanonicalInnerInstructionGroup; +pub use self::canonical_transaction::MdCanonicalInnerInstructionGroup; /// Canonical runtime-loaded addresses. -pub use crate::model::canonical_transaction::CanonicalLoadedAddresses; +pub use self::canonical_transaction::MdCanonicalLoadedAddresses; /// Canonical Solana message header. -pub use crate::model::canonical_transaction::CanonicalMessageHeader; +pub use self::canonical_transaction::MdCanonicalMessageHeader; /// Canonical transaction return data. -pub use crate::model::canonical_transaction::CanonicalReturnData; +pub use self::canonical_transaction::MdCanonicalReturnData; /// Canonical transaction reward. -pub use crate::model::canonical_transaction::CanonicalReward; +pub use self::canonical_transaction::MdCanonicalReward; /// Canonical exact token balance. -pub use crate::model::canonical_transaction::CanonicalTokenBalance; +pub use self::canonical_transaction::MdCanonicalTokenBalance; /// Source-independent canonical Solana transaction. -pub use crate::model::canonical_transaction::CanonicalTransaction; +pub use self::canonical_transaction::MdCanonicalTransaction; /// Canonical Solana transaction message. -pub use crate::model::canonical_transaction::CanonicalTransactionMessage; +pub use self::canonical_transaction::MdCanonicalTransactionMessage; /// Canonical Solana transaction execution metadata. -pub use crate::model::canonical_transaction::CanonicalTransactionMetadata; +pub use self::canonical_transaction::MdCanonicalTransactionMetadata; /// Canonical Solana transaction execution status. -pub use crate::model::canonical_transaction::CanonicalTransactionStatus; +pub use self::canonical_transaction::MdCanonicalTransactionStatus; /// Canonical Solana transaction version. -pub use crate::model::canonical_transaction::CanonicalTransactionVersion; +pub use self::canonical_transaction::MdCanonicalTransactionVersion; /// Protocol-level decoded event produced by a decoder. -pub use crate::model::decoded::DecodedProtocolEvent; +pub use self::decoded::MdDecodedProtocolEvent; /// Confidence level for a decoded event. -pub use crate::model::decoded::DecoderConfidence; +pub use self::decoded::MdDecoderConfidence; /// Source from which a decoded event was derived. -pub use crate::model::decoded::EventSourceKind; +pub use self::decoded::MdEventSourceKind; /// Business-level materialized event placeholder. -pub use crate::model::materialized::MaterializedEvent; +pub use self::materialized::MdMaterializedEvent; /// Materialized event family. -pub use crate::model::materialized::MaterializedEventFamily; +pub use self::materialized::MdMaterializedEventFamily; /// Canonical event code in `.` format. -pub use crate::model::nomenclature::EventCode; +pub use self::nomenclature::MdEventCode; /// High-level event family. -pub use crate::model::nomenclature::EventFamily; +pub use self::nomenclature::MdEventFamily; /// Event name without surface prefix. -pub use crate::model::nomenclature::EventName; +pub use self::nomenclature::MdEventName; /// Stable internal program code. -pub use crate::model::nomenclature::ProgramCode; +pub use self::nomenclature::MdProgramCode; /// Protocol family code, for example `raydium` or `meteora`. -pub use crate::model::nomenclature::ProtocolCode; +pub use self::nomenclature::MdProtocolCode; /// Concrete protocol surface code, for example `raydium_amm_v4`. -pub use crate::model::nomenclature::SurfaceCode; +pub use self::nomenclature::MdSurfaceCode; /// Generic program observation derived from a Solana instruction. -pub use crate::model::observation::ProgramObservation; +pub use self::observation::MdProgramObservation; /// Stable top-level or inner instruction path. -pub use crate::model::solana::InstructionPath; +pub use self::solana::MdInstructionPath; /// Solana program id. -pub use crate::model::solana::ProgramId; +pub use self::solana::MdProgramId; /// Solana public key. -pub use crate::model::solana::Pubkey; +pub use self::solana::MdPubkey; /// Solana transaction signature. -pub use crate::model::solana::Signature; +pub use self::solana::MdSignature; /// Solana slot. -pub use crate::model::solana::Slot; +pub use self::solana::MdSlot; -/// Source-neutral replay contracts. -pub mod replay; /// Version of the normalized core replay contract. -pub use crate::model::replay::CORE_REPLAY_INPUT_CONTRACT_VERSION; +pub use self::replay::MD_CORE_REPLAY_INPUT_CONTRACT_VERSION; /// Decoder replay input containing one instruction plus extracted transaction context. -pub use crate::model::replay::CoreInstructionReplayInput; +pub use self::replay::MdCoreInstructionReplayInput; diff --git a/kb-lib/src/model/canonical_transaction.rs b/kb-lib/src/model/canonical_transaction.rs index 9fbe464..3f10d93 100644 --- a/kb-lib/src/model/canonical_transaction.rs +++ b/kb-lib/src/model/canonical_transaction.rs @@ -7,12 +7,12 @@ use base64::Engine; // rust-rules: trait-import use sha2::Digest; // rust-rules: trait-import /// Current canonical transaction document version. -pub const CANONICAL_TRANSACTION_FORMAT_VERSION: u32 = 1; +pub const MD_CANONICAL_TRANSACTION_FORMAT_VERSION: u32 = 1; /// Source-independent canonical Solana transaction. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalTransaction { +pub struct MdCanonicalTransaction { /// Canonical contract version included in the hashed document. pub format_version: u32, /// Primary transaction signature as base58 text. @@ -22,19 +22,19 @@ pub struct CanonicalTransaction { /// Optional block timestamp as Unix seconds. pub block_time: std::option::Option, /// Transaction message version. - pub version: CanonicalTransactionVersion, + pub version: MdCanonicalTransactionVersion, /// All transaction signatures in message order. pub signatures: std::vec::Vec, /// Canonical transaction message. - pub message: CanonicalTransactionMessage, + pub message: MdCanonicalTransactionMessage, /// Optional execution metadata. - pub metadata: std::option::Option, + pub metadata: std::option::Option, } -impl CanonicalTransaction { +impl MdCanonicalTransaction { /// Validates the canonical transaction invariants. pub fn validate(&self) -> kb_core::Result<()> { - if self.format_version != crate::CANONICAL_TRANSACTION_FORMAT_VERSION { + if self.format_version != crate::MD_CANONICAL_TRANSACTION_FORMAT_VERSION { return std::result::Result::Err(kb_core::Error::invalid_state(format!( "unsupported canonical transaction format version: {}", self.format_version @@ -73,7 +73,7 @@ impl CanonicalTransaction { if let std::result::Result::Err(error) = message_result { return std::result::Result::Err(error); } - if self.version == CanonicalTransactionVersion::Legacy + if self.version == MdCanonicalTransactionVersion::Legacy && (!self.message.address_table_lookups.is_empty() || !self.message.loaded_addresses.writable.is_empty() || !self.message.loaded_addresses.readonly.is_empty()) @@ -146,7 +146,7 @@ impl CanonicalTransaction { /// Canonical Solana transaction version. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(tag = "kind", content = "number", rename_all = "snake_case")] -pub enum CanonicalTransactionVersion { +pub enum MdCanonicalTransactionVersion { /// Legacy transaction message. Legacy, /// Numbered versioned transaction message. @@ -156,7 +156,7 @@ pub enum CanonicalTransactionVersion { /// Canonical Solana message header. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalMessageHeader { +pub struct MdCanonicalMessageHeader { /// Number of required transaction signatures. pub num_required_signatures: u8, /// Number of readonly signed accounts. @@ -168,22 +168,22 @@ pub struct CanonicalMessageHeader { /// Canonical Solana transaction message. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalTransactionMessage { +pub struct MdCanonicalTransactionMessage { /// Message header. - pub header: CanonicalMessageHeader, + pub header: MdCanonicalMessageHeader, /// Static account keys in message order. pub static_account_keys: std::vec::Vec, /// Recent blockhash as base58 text. pub recent_blockhash: std::string::String, /// Top-level compiled instructions. - pub instructions: std::vec::Vec, + pub instructions: std::vec::Vec, /// Address lookup table references for versioned messages. - pub address_table_lookups: std::vec::Vec, + pub address_table_lookups: std::vec::Vec, /// Loaded writable and readonly addresses resolved by the runtime. - pub loaded_addresses: CanonicalLoadedAddresses, + pub loaded_addresses: MdCanonicalLoadedAddresses, } -impl CanonicalTransactionMessage { +impl MdCanonicalTransactionMessage { /// Returns the resolved account count including loaded addresses. pub fn resolved_account_count(&self) -> usize { return self.static_account_keys.len() @@ -262,7 +262,7 @@ impl CanonicalTransactionMessage { /// Canonical compiled Solana instruction. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalCompiledInstruction { +pub struct MdCanonicalCompiledInstruction { /// Resolved account index of the invoked program. pub program_id_index: u16, /// Resolved account indexes consumed by the instruction. @@ -273,7 +273,7 @@ pub struct CanonicalCompiledInstruction { pub stack_height: std::option::Option, } -impl CanonicalCompiledInstruction { +impl MdCanonicalCompiledInstruction { fn validate(&self, resolved_account_count: usize) -> kb_core::Result<()> { if usize::from(self.program_id_index) >= resolved_account_count { return std::result::Result::Err(kb_core::Error::invalid_state( @@ -301,7 +301,7 @@ impl CanonicalCompiledInstruction { /// Canonical address lookup table reference. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalAddressTableLookup { +pub struct MdCanonicalAddressTableLookup { /// Lookup table account key as base58 text. pub account_key: std::string::String, /// Writable lookup indexes. @@ -313,7 +313,7 @@ pub struct CanonicalAddressTableLookup { /// Runtime-loaded addresses for a versioned transaction. #[derive(Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalLoadedAddresses { +pub struct MdCanonicalLoadedAddresses { /// Writable loaded addresses in runtime order. pub writable: std::vec::Vec, /// Readonly loaded addresses in runtime order. @@ -323,7 +323,7 @@ pub struct CanonicalLoadedAddresses { /// Canonical transaction execution status. #[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "snake_case")] -pub enum CanonicalTransactionStatus { +pub enum MdCanonicalTransactionStatus { /// Transaction execution succeeded. Success, /// Transaction execution failed. @@ -333,9 +333,9 @@ pub enum CanonicalTransactionStatus { /// Canonical transaction execution metadata. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalTransactionMetadata { +pub struct MdCanonicalTransactionMetadata { /// Canonical execution status. - pub status: CanonicalTransactionStatus, + pub status: MdCanonicalTransactionStatus, /// Optional source-independent transaction error document. pub error: std::option::Option, /// Transaction fee in lamports. @@ -345,24 +345,24 @@ pub struct CanonicalTransactionMetadata { /// Account balances after execution in lamports. pub post_balances: std::vec::Vec, /// Inner instruction groups indexed by parent top-level instruction. - pub inner_instructions: std::vec::Vec, + pub inner_instructions: std::vec::Vec, /// Runtime log messages in execution order. pub log_messages: std::vec::Vec, /// Token balances before execution. - pub pre_token_balances: std::vec::Vec, + pub pre_token_balances: std::vec::Vec, /// Token balances after execution. - pub post_token_balances: std::vec::Vec, + pub post_token_balances: std::vec::Vec, /// Transaction rewards. - pub rewards: std::vec::Vec, + pub rewards: std::vec::Vec, /// Optional transaction return data. - pub return_data: std::option::Option, + pub return_data: std::option::Option, /// Optional consumed compute units. pub compute_units_consumed: std::option::Option, /// Optional runtime cost units. pub cost_units: std::option::Option, } -impl CanonicalTransactionMetadata { +impl MdCanonicalTransactionMetadata { fn validate( &self, resolved_account_count: usize, @@ -379,14 +379,14 @@ impl CanonicalTransactionMetadata { )); } match self.status { - CanonicalTransactionStatus::Success => { + MdCanonicalTransactionStatus::Success => { if self.error.is_some() { return std::result::Result::Err(kb_core::Error::invalid_state( "successful canonical transaction must not contain an error", )); } }, - CanonicalTransactionStatus::Failed => { + MdCanonicalTransactionStatus::Failed => { if self.error.is_none() { return std::result::Result::Err(kb_core::Error::invalid_state( "failed canonical transaction must contain an error", @@ -453,17 +453,17 @@ impl CanonicalTransactionMetadata { /// Group of inner instructions attached to one top-level instruction. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalInnerInstructionGroup { +pub struct MdCanonicalInnerInstructionGroup { /// Parent top-level instruction index. pub parent_instruction_index: u16, /// Inner instructions in runtime order. - pub instructions: std::vec::Vec, + pub instructions: std::vec::Vec, } /// Exact SPL token balance representation. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalTokenBalance { +pub struct MdCanonicalTokenBalance { /// Resolved account index. pub account_index: u16, /// Token mint public key. @@ -480,7 +480,7 @@ pub struct CanonicalTokenBalance { pub decimal_amount: std::string::String, } -impl CanonicalTokenBalance { +impl MdCanonicalTokenBalance { /// Creates an exact canonical token balance without provider-specific UI formatting. pub fn new( account_index: u16, @@ -552,7 +552,7 @@ impl CanonicalTokenBalance { /// Canonical transaction reward. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalReward { +pub struct MdCanonicalReward { /// Reward account public key. pub pubkey: std::string::String, /// Signed lamport delta. @@ -568,7 +568,7 @@ pub struct CanonicalReward { /// Canonical transaction return data. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] -pub struct CanonicalReturnData { +pub struct MdCanonicalReturnData { /// Program that returned the data. pub program_id: std::string::String, /// Return bytes encoded as standard base64. @@ -671,18 +671,18 @@ fn validate_base58_length( #[cfg(test)] mod tests { - fn sample_transaction() -> crate::CanonicalTransaction { - return crate::CanonicalTransaction { - format_version: crate::CANONICAL_TRANSACTION_FORMAT_VERSION, + fn sample_transaction() -> crate::MdCanonicalTransaction { + return crate::MdCanonicalTransaction { + format_version: crate::MD_CANONICAL_TRANSACTION_FORMAT_VERSION, primary_signature: "2Ana1pUpv2ZbMVkwF5FXapYeBEjdxDatLn7nvJkhgTSXbs59SyZSx866bXirPgj8QQVB57uxHJBG1YFvkRbFj4T".to_string(), slot: 42, block_time: std::option::Option::Some(1_700_000_000), - version: crate::CanonicalTransactionVersion::Legacy, + version: crate::MdCanonicalTransactionVersion::Legacy, signatures: std::vec![ "2Ana1pUpv2ZbMVkwF5FXapYeBEjdxDatLn7nvJkhgTSXbs59SyZSx866bXirPgj8QQVB57uxHJBG1YFvkRbFj4T".to_string(), ], - message: crate::CanonicalTransactionMessage { - header: crate::CanonicalMessageHeader { + message: crate::MdCanonicalTransactionMessage { + header: crate::MdCanonicalMessageHeader { num_required_signatures: 1, num_readonly_signed_accounts: 0, num_readonly_unsigned_accounts: 1, @@ -692,17 +692,17 @@ mod tests { "SysvarC1ock11111111111111111111111111111111".to_string(), ], recent_blockhash: "11111111111111111111111111111111".to_string(), - instructions: std::vec![crate::CanonicalCompiledInstruction { + instructions: std::vec![crate::MdCanonicalCompiledInstruction { program_id_index: 0, account_indexes: std::vec![1], data_base64: "AQ==".to_string(), stack_height: std::option::Option::Some(1), }], address_table_lookups: std::vec::Vec::new(), - loaded_addresses: crate::CanonicalLoadedAddresses::default(), + loaded_addresses: crate::MdCanonicalLoadedAddresses::default(), }, - metadata: std::option::Option::Some(crate::CanonicalTransactionMetadata { - status: crate::CanonicalTransactionStatus::Success, + metadata: std::option::Option::Some(crate::MdCanonicalTransactionMetadata { + status: crate::MdCanonicalTransactionStatus::Success, error: std::option::Option::None, fee: 5000, pre_balances: std::vec![10_000, 1], @@ -740,14 +740,14 @@ mod tests { let mut first = sample_transaction(); let mut second = sample_transaction(); if let std::option::Option::Some(metadata) = &mut first.metadata { - metadata.status = crate::CanonicalTransactionStatus::Failed; + metadata.status = crate::MdCanonicalTransactionStatus::Failed; metadata.error = std::option::Option::Some(serde_json::json!({ "z": 3, "nested": {"b": 2, "a": 1} })); } if let std::option::Option::Some(metadata) = &mut second.metadata { - metadata.status = crate::CanonicalTransactionStatus::Failed; + metadata.status = crate::MdCanonicalTransactionStatus::Failed; let parse_result = serde_json::from_str::(r#"{"nested":{"a":1,"b":2},"z":3}"#); metadata.error = match parse_result { @@ -777,7 +777,7 @@ mod tests { #[test] fn token_decimal_amount_is_derived_without_source_ui_formatting() { - let result = crate::CanonicalTokenBalance::new( + let result = crate::MdCanonicalTokenBalance::new( 0, "So11111111111111111111111111111111111111112", std::option::Option::None, @@ -811,7 +811,7 @@ mod tests { fn validation_rejects_inconsistent_status_and_error() { let mut transaction = sample_transaction(); if let std::option::Option::Some(metadata) = &mut transaction.metadata { - metadata.status = crate::CanonicalTransactionStatus::Failed; + metadata.status = crate::MdCanonicalTransactionStatus::Failed; } let result = transaction.validate(); assert!(result.is_err()); diff --git a/kb-lib/src/model/decoded.rs b/kb-lib/src/model/decoded.rs index 4b9443d..7fca08e 100644 --- a/kb-lib/src/model/decoded.rs +++ b/kb-lib/src/model/decoded.rs @@ -11,7 +11,7 @@ use ts_rs::TS; // rust-rules: derive-import export, export_to = "../frontend/ts/bindings/kb_model/decoded/EventSourceKind.ts" )] -pub enum EventSourceKind { +pub enum MdEventSourceKind { /// Top-level instruction. Instruction, /// Inner instruction. @@ -38,7 +38,7 @@ pub enum EventSourceKind { export, export_to = "../frontend/ts/bindings/kb_model/decoded/DecoderConfidence.ts" )] -pub enum DecoderConfidence { +pub enum MdDecoderConfidence { /// Exact manual decode. Exact, /// Exact IDL-based decode. @@ -61,27 +61,27 @@ pub enum DecoderConfidence { export, export_to = "../frontend/ts/bindings/kb_model/decoded/DecodedProtocolEvent.ts" )] -pub struct DecodedProtocolEvent { +pub struct MdDecodedProtocolEvent { /// Transaction signature. - pub signature: crate::Signature, + pub signature: crate::MdSignature, /// Transaction slot. - pub slot: crate::Slot, + pub slot: crate::MdSlot, /// Instruction path. - pub instruction_path: crate::InstructionPath, + pub instruction_path: crate::MdInstructionPath, /// Program id. - pub program_id: crate::ProgramId, + pub program_id: crate::MdProgramId, /// Protocol family. - pub protocol_code: crate::ProtocolCode, + pub protocol_code: crate::MdProtocolCode, /// Protocol surface. - pub surface_code: crate::SurfaceCode, + pub surface_code: crate::MdSurfaceCode, /// Canonical event code. - pub event_code: crate::EventCode, + pub event_code: crate::MdEventCode, /// Short event name. - pub event_name: crate::EventName, + pub event_name: crate::MdEventName, /// Event family. - pub event_family: crate::EventFamily, + pub event_family: crate::MdEventFamily, /// Event source kind. - pub source_kind: crate::EventSourceKind, + pub source_kind: crate::MdEventSourceKind, /// Decoder confidence. - pub confidence: crate::DecoderConfidence, + pub confidence: crate::MdDecoderConfidence, } diff --git a/kb-lib/src/model/materialized.rs b/kb-lib/src/model/materialized.rs index 7121220..b704d77 100644 --- a/kb-lib/src/model/materialized.rs +++ b/kb-lib/src/model/materialized.rs @@ -11,7 +11,7 @@ use ts_rs::TS; // rust-rules: derive-import export, export_to = "../frontend/ts/bindings/kb_model/materialized/MaterializedEventFamily.ts" )] -pub enum MaterializedEventFamily { +pub enum MdMaterializedEventFamily { /// Trade materialization. Trade, /// Liquidity materialization. @@ -68,13 +68,13 @@ pub enum MaterializedEventFamily { export, export_to = "../frontend/ts/bindings/kb_model/materialized/MaterializedEvent.ts" )] -pub struct MaterializedEvent { +pub struct MdMaterializedEvent { /// Source transaction signature. - pub signature: crate::Signature, + pub signature: crate::MdSignature, /// Source transaction slot. - pub slot: crate::Slot, + pub slot: crate::MdSlot, /// Source decoded family. - pub decoded_family: crate::EventFamily, + pub decoded_family: crate::MdEventFamily, /// Materialized family. - pub materialized_family: crate::MaterializedEventFamily, + pub materialized_family: crate::MdMaterializedEventFamily, } diff --git a/kb-lib/src/model/nomenclature.rs b/kb-lib/src/model/nomenclature.rs index 5ec0bd3..196b864 100644 --- a/kb-lib/src/model/nomenclature.rs +++ b/kb-lib/src/model/nomenclature.rs @@ -11,7 +11,7 @@ use ts_rs::TS; // rust-rules: derive-import export, export_to = "../frontend/ts/bindings/kb_model/nomenclature/ProgramCode.ts" )] -pub struct ProgramCode(pub std::string::String); +pub struct MdProgramCode(pub std::string::String); /// Protocol family code, for example `raydium` or `meteora`. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] @@ -19,7 +19,7 @@ pub struct ProgramCode(pub std::string::String); export, export_to = "../frontend/ts/bindings/kb_model/nomenclature/ProtocolCode.ts" )] -pub struct ProtocolCode(pub std::string::String); +pub struct MdProtocolCode(pub std::string::String); /// Concrete protocol surface code, for example `raydium_amm_v4`. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] @@ -27,17 +27,17 @@ pub struct ProtocolCode(pub std::string::String); export, export_to = "../frontend/ts/bindings/kb_model/nomenclature/SurfaceCode.ts" )] -pub struct SurfaceCode(pub std::string::String); +pub struct MdSurfaceCode(pub std::string::String); /// Event name without surface prefix. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] #[ts(export, export_to = "../frontend/ts/bindings/kb_model/nomenclature/EventName.ts")] -pub struct EventName(pub std::string::String); +pub struct MdEventName(pub std::string::String); /// Canonical event code in `.` format. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] #[ts(export, export_to = "../frontend/ts/bindings/kb_model/nomenclature/EventCode.ts")] -pub struct EventCode(pub std::string::String); +pub struct MdEventCode(pub std::string::String); /// High-level event family. #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] @@ -45,7 +45,7 @@ pub struct EventCode(pub std::string::String); export, export_to = "../frontend/ts/bindings/kb_model/nomenclature/EventFamily.ts" )] -pub enum EventFamily { +pub enum MdEventFamily { /// Swap or buy/sell event. Trade, /// Liquidity deposit/withdraw or equivalent. diff --git a/kb-lib/src/model/observation.rs b/kb-lib/src/model/observation.rs index 1bf5ed3..468bea0 100644 --- a/kb-lib/src/model/observation.rs +++ b/kb-lib/src/model/observation.rs @@ -11,15 +11,15 @@ use ts_rs::TS; // rust-rules: derive-import export, export_to = "../frontend/ts/bindings/kb_model/observation/ProgramObservation.ts" )] -pub struct ProgramObservation { +pub struct MdProgramObservation { /// Transaction signature. - pub signature: crate::Signature, + pub signature: crate::MdSignature, /// Transaction slot. - pub slot: crate::Slot, + pub slot: crate::MdSlot, /// Instruction path. - pub instruction_path: crate::InstructionPath, + pub instruction_path: crate::MdInstructionPath, /// Program id. - pub program_id: crate::ProgramId, + pub program_id: crate::MdProgramId, /// Optional 8-byte discriminator in hexadecimal. pub discriminator_8: std::option::Option, /// Raw instruction data length. diff --git a/kb-lib/src/model/replay.rs b/kb-lib/src/model/replay.rs index 7cd94ce..1e18fc8 100644 --- a/kb-lib/src/model/replay.rs +++ b/kb-lib/src/model/replay.rs @@ -4,11 +4,11 @@ //! Source-neutral instruction replay input shared by decoders and stores. /// Version of the normalized core replay contract. -pub const CORE_REPLAY_INPUT_CONTRACT_VERSION: u32 = 2; +pub const MD_CORE_REPLAY_INPUT_CONTRACT_VERSION: u32 = 2; /// Decoder replay input containing one instruction plus extracted transaction context. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct CoreInstructionReplayInput { +pub struct MdCoreInstructionReplayInput { /// Version of the normalized core replay contract. pub core_contract_version: u32, /// Stable deduplication key for this replay input. @@ -45,7 +45,7 @@ pub struct CoreInstructionReplayInput { pub balance_changes_json: serde_json::Value, } -impl CoreInstructionReplayInput { +impl MdCoreInstructionReplayInput { /// Builds a decoder replay input after validating its stable identity and array context. #[allow(clippy::too_many_arguments)] pub fn new( @@ -71,7 +71,7 @@ impl CoreInstructionReplayInput { )); } let value = Self { - core_contract_version: crate::CORE_REPLAY_INPUT_CONTRACT_VERSION, + core_contract_version: crate::MD_CORE_REPLAY_INPUT_CONTRACT_VERSION, replay_input_key: replay_input_key.into(), signature: signature.into(), slot, @@ -98,7 +98,7 @@ impl CoreInstructionReplayInput { /// Validates the stable replay identity and contract version. pub fn validate(&self) -> kb_core::Result<()> { - if self.core_contract_version != crate::CORE_REPLAY_INPUT_CONTRACT_VERSION { + if self.core_contract_version != crate::MD_CORE_REPLAY_INPUT_CONTRACT_VERSION { return std::result::Result::Err(kb_core::Error::invalid_state( "unsupported core replay input contract version", )); diff --git a/kb-lib/src/model/solana.rs b/kb-lib/src/model/solana.rs index 2e2a28b..95f3d30 100644 --- a/kb-lib/src/model/solana.rs +++ b/kb-lib/src/model/solana.rs @@ -8,7 +8,7 @@ use ts_rs::TS; // rust-rules: derive-import /// Solana transaction signature. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] #[ts(export, export_to = "../frontend/ts/bindings/kb_model/solana/Signature.ts")] -pub struct Signature(pub std::string::String); +pub struct MdSignature(pub std::string::String); /// Solana slot. #[derive( @@ -25,19 +25,19 @@ pub struct Signature(pub std::string::String); TS, )] #[ts(export, export_to = "../frontend/ts/bindings/kb_model/solana/Slot.ts")] -pub struct Slot(pub u64); +pub struct MdSlot(pub u64); /// Solana program id. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] #[ts(export, export_to = "../frontend/ts/bindings/kb_model/solana/ProgramId.ts")] -pub struct ProgramId(pub std::string::String); +pub struct MdProgramId(pub std::string::String); /// Solana public key. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] #[ts(export, export_to = "../frontend/ts/bindings/kb_model/solana/Pubkey.ts")] -pub struct Pubkey(pub std::string::String); +pub struct MdPubkey(pub std::string::String); /// Stable top-level or inner instruction path. #[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)] #[ts(export, export_to = "../frontend/ts/bindings/kb_model/solana/InstructionPath.ts")] -pub struct InstructionPath(pub std::string::String); +pub struct MdInstructionPath(pub std::string::String); diff --git a/kb-lib/tests/external_decoder_api.rs b/kb-lib/tests/external_decoder_api.rs new file mode 100644 index 0000000..6da1411 --- /dev/null +++ b/kb-lib/tests/external_decoder_api.rs @@ -0,0 +1,42 @@ +// file: kb-lib/tests/external_decoder_api.rs +// version: 1 + +//! Downstream-style compilation contract for externally implemented decoders. + +struct ExternalDecoder; + +impl kb_lib::DcApiProtocolDecoder for ExternalDecoder { + fn decoder_name(&self) -> &'static str { + return "external_decoder"; + } + + fn decoder_version(&self) -> &'static str { + return "1"; + } + + fn program_ids(&self) -> &'static [&'static str] { + return &[]; + } + + fn supports_observation( + &self, + _observation: &kb_lib::MdProgramObservation, + ) -> kb_lib::DcApiDecoderSupport { + return kb_lib::DcApiDecoderSupport::No; + } + + fn decode_observation( + &self, + _observation: &kb_lib::MdProgramObservation, + ) -> kb_core::Result> { + return std::result::Result::Ok(std::vec::Vec::new()); + } +} + +#[test] +fn external_decoder_uses_only_the_public_kb_lib_contract() { + let decoder: &dyn kb_lib::DcApiProtocolDecoder = &ExternalDecoder; + assert_eq!(decoder.decoder_name(), "external_decoder"); + assert_eq!(decoder.decoder_version(), "1"); + assert!(decoder.program_ids().is_empty()); +} diff --git a/kb-lib/tests/external_executor_api.rs b/kb-lib/tests/external_executor_api.rs new file mode 100644 index 0000000..ebf2cfd --- /dev/null +++ b/kb-lib/tests/external_executor_api.rs @@ -0,0 +1,46 @@ +// file: kb-lib/tests/external_executor_api.rs +// version: 1 + +//! Downstream-style compilation contract for externally implemented executors. + +struct ExternalExecutor; + +impl kb_lib::ExApiInstructionExecutor for ExternalExecutor { + fn executor_name(&self) -> &'static str { + return "external_executor"; + } + + fn executor_version(&self) -> &'static str { + return "1"; + } + + fn program_ids(&self) -> &'static [&'static str] { + return &[]; + } + + fn supports_request( + &self, + _request: &kb_lib::ExApiExecutionRequest, + ) -> kb_lib::ExApiExecutionSupport { + return kb_lib::ExApiExecutionSupport::No; + } + + fn build_plan( + &self, + request: &kb_lib::ExApiExecutionRequest, + ) -> kb_core::Result { + return std::result::Result::Ok(kb_lib::ExApiExecutionPlan { + executor_name: self.executor_name().to_string(), + instruction_count: 0, + payload_json: request.payload_json.clone(), + }); + } +} + +#[test] +fn external_executor_uses_only_the_public_kb_lib_contract() { + let executor: &dyn kb_lib::ExApiInstructionExecutor = &ExternalExecutor; + assert_eq!(executor.executor_name(), "external_executor"); + assert_eq!(executor.executor_version(), "1"); + assert!(executor.program_ids().is_empty()); +} diff --git a/kb-lib/tests/external_materializer_api.rs b/kb-lib/tests/external_materializer_api.rs index cd9c823..60a8f5e 100644 --- a/kb-lib/tests/external_materializer_api.rs +++ b/kb-lib/tests/external_materializer_api.rs @@ -1,42 +1,62 @@ // file: kb-lib/tests/external_materializer_api.rs -// version: 1 +// version: 2 //! Downstream-style compilation contract for externally implemented materializers. -const ACCEPTED_FAMILIES: &[kb_lib::EventFamily] = &[kb_lib::EventFamily::Audit]; +const ACCEPTED_FAMILIES: &[kb_lib::MdEventFamily] = &[kb_lib::MdEventFamily::Audit]; struct ExternalAuditMaterializer; -impl kb_lib::EventMaterializer for ExternalAuditMaterializer { - fn identity(&self) -> kb_lib::MaterializerIdentity { - return kb_lib::MaterializerIdentity { +fn assert_event_materializer() {} + +fn assert_legacy_materializer() {} + +impl kb_lib::MtApiEventMaterializer for ExternalAuditMaterializer { + fn identity(&self) -> kb_lib::MtApiMaterializerIdentity { + return kb_lib::MtApiMaterializerIdentity { name: "external_audit_materializer".to_string(), version: "1".to_string(), }; } - fn accepted_families(&self) -> &'static [kb_lib::EventFamily] { + fn accepted_families(&self) -> &'static [kb_lib::MdEventFamily] { return ACCEPTED_FAMILIES; } fn transaction_policy( &self, - _family: kb_lib::EventFamily, - ) -> kb_lib::MaterializationTransactionPolicy { - return kb_lib::MaterializationTransactionPolicy::SuccessfulOrFailedAudit; + _family: kb_lib::MdEventFamily, + ) -> kb_lib::MtApiMaterializationTransactionPolicy { + return kb_lib::MtApiMaterializationTransactionPolicy::SuccessfulOrFailedAudit; } fn materialize( &self, - _observation: &kb_lib::DecodedObservation, - ) -> kb_lib::MaterializerExecutionResult { - return kb_lib::MaterializerExecutionResult::ignored(); + _observation: &kb_lib::DcApiDecodedObservation, + ) -> kb_lib::MtApiMaterializerExecutionResult { + return kb_lib::MtApiMaterializerExecutionResult::ignored(); } } #[test] fn external_materializer_uses_only_the_public_kb_lib_contract() { - let materializer: &dyn kb_lib::EventMaterializer = &ExternalAuditMaterializer; + let materializer: &dyn kb_lib::MtApiEventMaterializer = &ExternalAuditMaterializer; assert_eq!(materializer.identity().name, "external_audit_materializer"); assert_eq!(materializer.accepted_families(), ACCEPTED_FAMILIES); + assert_event_materializer::(); + assert_event_materializer::(); + assert_event_materializer::(); + assert_event_materializer::(); + assert_event_materializer::(); + assert_event_materializer::(); + assert_event_materializer::(); + assert_event_materializer::(); + assert_legacy_materializer::(); + let _ = kb_lib::materializer_admin_materialize_elgamal_registry_state_snapshot; + let _ = kb_lib::materialize_metaplex_account_snapshot; + let _ = kb_lib::materialize_metaplex_metadata_snapshot; + let _ = kb_lib::materialize_token2022_admin_state_snapshots; + let _ = kb_lib::materialize_token2022_fee_state_snapshots; + let _ = kb_lib::materialize_token2022_metadata_snapshot; + let _ = kb_lib::materialize_token2022_state_snapshot; } diff --git a/kb-logging/src/lib.rs b/kb-logging/src/lib.rs index 29dce3e..90207bc 100644 --- a/kb-logging/src/lib.rs +++ b/kb-logging/src/lib.rs @@ -10,7 +10,7 @@ mod constants; /// Canonical tracing target for this crate. -pub(crate) use crate::constants::TRACING_TARGET; +pub(crate) use self::constants::TRACING_TARGET; /// Returns the canonical tracing target. pub fn tracing_target() -> &'static str { diff --git a/kb-program-ids/src/constants.rs b/kb-program-ids/src/constants.rs index c4229a4..dc64733 100644 --- a/kb-program-ids/src/constants.rs +++ b/kb-program-ids/src/constants.rs @@ -45,9 +45,9 @@ pub const SPL_MEMO_V4_PROGRAM_ID: &str = "Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFa /// Classic SPL Token program identifier. pub const SPL_TOKEN_PROGRAM_ID: &str = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; /// SPL Token-2022 program identifier. -pub const SPL_TOKEN_2022_PROGRAM_ID: &str = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"; +pub const SPL_TOKEN2022_PROGRAM_ID: &str = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"; /// SPL Token-2022 ElGamal public-key registry program identifier. -pub const SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID: &str = +pub const SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID: &str = "regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg"; /// Historical Stake configuration account identifier. pub const STAKE_CONFIG_ACCOUNT_ID: &str = "StakeConfig11111111111111111111111111111111"; @@ -242,12 +242,12 @@ pub(crate) const PROGRAM_ID_ENTRIES: &[crate::ProgramIdEntry] = &[ address: crate::SPL_TOKEN_PROGRAM_ID, }, crate::ProgramIdEntry { - name: "spl_token_2022", - address: crate::SPL_TOKEN_2022_PROGRAM_ID, + name: "spl_token2022", + address: crate::SPL_TOKEN2022_PROGRAM_ID, }, crate::ProgramIdEntry { - name: "spl_token_2022_elgamal_registry", - address: crate::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, + name: "spl_token2022_elgamal_registry", + address: crate::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, }, crate::ProgramIdEntry { name: "stake_config", diff --git a/kb-program-ids/src/lib.rs b/kb-program-ids/src/lib.rs index 514743e..422fe48 100644 --- a/kb-program-ids/src/lib.rs +++ b/kb-program-ids/src/lib.rs @@ -55,12 +55,12 @@ pub use constants::SPL_MEMO_V1_PROGRAM_ID; pub use constants::SPL_MEMO_V3_PROGRAM_ID; /// Current SPL Memo v4 program identifier. pub use constants::SPL_MEMO_V4_PROGRAM_ID; -/// SPL Token-2022 ElGamal public-key registry program identifier. -pub use constants::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID; -/// SPL Token-2022 program identifier. -pub use constants::SPL_TOKEN_2022_PROGRAM_ID; /// Classic SPL Token program identifier. pub use constants::SPL_TOKEN_PROGRAM_ID; +/// SPL Token-2022 ElGamal public-key registry program identifier. +pub use constants::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID; +/// SPL Token-2022 program identifier. +pub use constants::SPL_TOKEN2022_PROGRAM_ID; /// Historical Stake configuration account identifier. pub use constants::STAKE_CONFIG_ACCOUNT_ID; /// Compatibility alias for the historical Stake configuration account identifier. diff --git a/kb-program-ids/src/programs.rs b/kb-program-ids/src/programs.rs index b3533ec..5baa606 100644 --- a/kb-program-ids/src/programs.rs +++ b/kb-program-ids/src/programs.rs @@ -128,8 +128,8 @@ mod tests { crate::SPL_MEMO_V3_PROGRAM_ID, crate::SPL_MEMO_V4_PROGRAM_ID, crate::SPL_TOKEN_PROGRAM_ID, - crate::SPL_TOKEN_2022_PROGRAM_ID, - crate::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID, + crate::SPL_TOKEN2022_PROGRAM_ID, + crate::SPL_TOKEN2022_ELGAMAL_REGISTRY_PROGRAM_ID, crate::ASSOCIATED_TOKEN_PROGRAM_ID, crate::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID, ]; diff --git a/kb-store/README.md b/kb-store/README.md index 42f6365..34b1fab 100644 --- a/kb-store/README.md +++ b/kb-store/README.md @@ -45,7 +45,7 @@ kb-core kb-lib ← kb-store ``` -`CoreInstructionReplayInput` et sa version de contrat appartiennent à `kb-lib`, car ils sont partagés avec les décodeurs. `kb-store` les consomme et les réexporte. `kb-lib` ne dépend jamais de `kb-store`. +`MdCoreInstructionReplayInput` et sa version de contrat appartiennent à `kb-lib`, car ils sont partagés avec les décodeurs. `kb-store` les consomme et les réexporte. `kb-lib` ne dépend jamais de `kb-store`. `kb-store` ne dépend pas de `kb-config`. L’application résout sa configuration, puis construit explicitement `PostgresStoreOptions`. Cette séparation évite de coupler la persistance à la forme évolutive des profils. diff --git a/kb-store/src/contracts/dto/core.rs b/kb-store/src/contracts/dto/core.rs index 980ed7e..ece51d1 100644 --- a/kb-store/src/contracts/dto/core.rs +++ b/kb-store/src/contracts/dto/core.rs @@ -764,7 +764,7 @@ mod tests { #[test] fn replay_input_rejects_empty_key() { - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( " ", "abc", 1, @@ -786,7 +786,7 @@ mod tests { #[test] fn replay_input_accepts_ordered_outer_instruction_array() { - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "abc:2", "abc", 1, @@ -831,7 +831,7 @@ mod tests { #[test] fn replay_input_rejects_non_array_outer_instruction_context() { - let result = crate::CoreInstructionReplayInput::new( + let result = crate::MdCoreInstructionReplayInput::new( "abc:0", "abc", 1, diff --git a/kb-store/src/contracts/dto/event.rs b/kb-store/src/contracts/dto/event.rs index 7e3f2a6..85b0f0c 100644 --- a/kb-store/src/contracts/dto/event.rs +++ b/kb-store/src/contracts/dto/event.rs @@ -54,7 +54,7 @@ pub struct DecodedEventInsert { impl DecodedEventInsert { /// Builds a decoded event insert contract from the shared decoded model. pub fn from_model( - event: &kb_lib::DecodedProtocolEvent, + event: &kb_lib::MdDecodedProtocolEvent, payload_json: serde_json::Value, ) -> kb_core::Result { if event.signature.0.trim().is_empty() { diff --git a/kb-store/src/contracts/dto/raw.rs b/kb-store/src/contracts/dto/raw.rs index deae8e4..4f98a89 100644 --- a/kb-store/src/contracts/dto/raw.rs +++ b/kb-store/src/contracts/dto/raw.rs @@ -107,7 +107,7 @@ impl RawTransactionInsert { } /// Builds a storage insert from the source-independent canonical transaction model. - pub fn from_canonical(transaction: &kb_lib::CanonicalTransaction) -> kb_core::Result { + pub fn from_canonical(transaction: &kb_lib::MdCanonicalTransaction) -> kb_core::Result { let canonical_json_result = transaction.to_canonical_json(); let canonical_json = match canonical_json_result { std::result::Result::Ok(value) => value, @@ -498,18 +498,18 @@ mod tests { assert!(result.is_err()); } - fn canonical_transaction_fixture() -> kb_lib::CanonicalTransaction { - return kb_lib::CanonicalTransaction { - format_version: kb_lib::CANONICAL_TRANSACTION_FORMAT_VERSION, + fn canonical_transaction_fixture() -> kb_lib::MdCanonicalTransaction { + return kb_lib::MdCanonicalTransaction { + format_version: kb_lib::MD_CANONICAL_TRANSACTION_FORMAT_VERSION, primary_signature: "2Ana1pUpv2ZbMVkwF5FXapYeBEjdxDatLn7nvJkhgTSXbs59SyZSx866bXirPgj8QQVB57uxHJBG1YFvkRbFj4T".to_string(), slot: 9, block_time: std::option::Option::None, - version: kb_lib::CanonicalTransactionVersion::Legacy, + version: kb_lib::MdCanonicalTransactionVersion::Legacy, signatures: std::vec![ "2Ana1pUpv2ZbMVkwF5FXapYeBEjdxDatLn7nvJkhgTSXbs59SyZSx866bXirPgj8QQVB57uxHJBG1YFvkRbFj4T".to_string(), ], - message: kb_lib::CanonicalTransactionMessage { - header: kb_lib::CanonicalMessageHeader { + message: kb_lib::MdCanonicalTransactionMessage { + header: kb_lib::MdCanonicalMessageHeader { num_required_signatures: 1, num_readonly_signed_accounts: 0, num_readonly_unsigned_accounts: 1, @@ -519,17 +519,17 @@ mod tests { "ComputeBudget111111111111111111111111111111".to_string(), ], recent_blockhash: "11111111111111111111111111111111".to_string(), - instructions: std::vec![kb_lib::CanonicalCompiledInstruction { + instructions: std::vec![kb_lib::MdCanonicalCompiledInstruction { program_id_index: 1, account_indexes: std::vec![0], data_base64: "AQ==".to_string(), stack_height: std::option::Option::Some(1), }], address_table_lookups: std::vec::Vec::new(), - loaded_addresses: kb_lib::CanonicalLoadedAddresses::default(), + loaded_addresses: kb_lib::MdCanonicalLoadedAddresses::default(), }, - metadata: std::option::Option::Some(kb_lib::CanonicalTransactionMetadata { - status: kb_lib::CanonicalTransactionStatus::Success, + metadata: std::option::Option::Some(kb_lib::MdCanonicalTransactionMetadata { + status: kb_lib::MdCanonicalTransactionStatus::Success, error: std::option::Option::None, fee: 5000, pre_balances: std::vec![10000, 1], @@ -556,7 +556,10 @@ mod tests { }; assert_eq!(insert.signature, transaction.primary_signature); assert_eq!(insert.slot, transaction.slot); - assert_eq!(insert.canonical_format_version, kb_lib::CANONICAL_TRANSACTION_FORMAT_VERSION); + assert_eq!( + insert.canonical_format_version, + kb_lib::MD_CANONICAL_TRANSACTION_FORMAT_VERSION + ); assert_eq!(insert.canonical_json_hash.as_deref().map(|value| return value.len()), Some(64)); } diff --git a/kb-store/src/contracts/repository.rs b/kb-store/src/contracts/repository.rs index 2c397a8..6fa7cd7 100644 --- a/kb-store/src/contracts/repository.rs +++ b/kb-store/src/contracts/repository.rs @@ -22,7 +22,7 @@ pub trait RawTransactionStore { /// Returns true when a canonical transaction signature is already stored. async fn has_raw_transaction_signature( &self, - signature: &kb_lib::Signature, + signature: &kb_lib::MdSignature, ) -> kb_core::Result; /// Returns true when a transaction observation key is already stored. @@ -99,7 +99,7 @@ pub trait CoreTransactionStore { &self, filter: &crate::CoreInstructionReplayFilter, page_request: &crate::PageRequest, - ) -> kb_core::Result>; + ) -> kb_core::Result>; /// Updates one normalized core instruction lifecycle state. async fn mark_core_instruction_lifecycle( @@ -144,7 +144,7 @@ pub trait DecodePipelineStore { async fn list_decode_inputs( &self, filter: &crate::DecodeSelectionFilter, - ) -> kb_core::Result>; + ) -> kb_core::Result>; /// Returns true when the same processor version already succeeded for the same input hash. async fn is_decode_current( @@ -199,7 +199,7 @@ pub trait ProgramObservationStore { /// Stores program observations. async fn store_observations( &self, - observations: &[kb_lib::ProgramObservation], + observations: &[kb_lib::MdProgramObservation], ) -> kb_core::Result; } diff --git a/kb-store/src/lib.rs b/kb-store/src/lib.rs index 80fb851..247c3a6 100644 --- a/kb-store/src/lib.rs +++ b/kb-store/src/lib.rs @@ -11,247 +11,247 @@ mod contracts; mod postgres; /// Canonical tracing target for storage operations. -pub(crate) use crate::constants::TRACING_TARGET; +pub(crate) use self::constants::TRACING_TARGET; /// Core account key insert contract. -pub use crate::contracts::CoreAccountKeyInsert; +pub use self::contracts::CoreAccountKeyInsert; /// Core account key SQL-like row contract. -pub use crate::contracts::CoreAccountKeyRow; +pub use self::contracts::CoreAccountKeyRow; /// Core account key source category. -pub use crate::contracts::CoreAccountKeySource; +pub use self::contracts::CoreAccountKeySource; /// Core balance change insert contract. -pub use crate::contracts::CoreBalanceChangeInsert; +pub use self::contracts::CoreBalanceChangeInsert; /// Core balance change kind. -pub use crate::contracts::CoreBalanceChangeKind; +pub use self::contracts::CoreBalanceChangeKind; /// Core balance change SQL-like row contract. -pub use crate::contracts::CoreBalanceChangeRow; +pub use self::contracts::CoreBalanceChangeRow; /// Complete normalized core extraction write bundle. -pub use crate::contracts::CoreExtractionBundle; +pub use self::contracts::CoreExtractionBundle; /// Failure details persisted for one canonical to core extraction attempt. -pub use crate::contracts::CoreExtractionFailure; +pub use self::contracts::CoreExtractionFailure; /// Bounded canonical transaction selection filter for core extraction. -pub use crate::contracts::CoreExtractionSelectionFilter; +pub use self::contracts::CoreExtractionSelectionFilter; /// Canonical transaction to core extraction storage behavior. -pub use crate::contracts::CoreExtractionStore; +pub use self::contracts::CoreExtractionStore; /// Core inner instruction insert contract. -pub use crate::contracts::CoreInnerInstructionInsert; +pub use self::contracts::CoreInnerInstructionInsert; /// Core inner instruction SQL-like row contract. -pub use crate::contracts::CoreInnerInstructionRow; +pub use self::contracts::CoreInnerInstructionRow; /// Core instruction insert contract. -pub use crate::contracts::CoreInstructionInsert; +pub use self::contracts::CoreInstructionInsert; /// Core instruction lifecycle mark request. -pub use crate::contracts::CoreInstructionLifecycleMark; +pub use self::contracts::CoreInstructionLifecycleMark; /// Core instruction processing state. -pub use crate::contracts::CoreInstructionProcessingState; +pub use self::contracts::CoreInstructionProcessingState; /// Core instruction replay filter contract. -pub use crate::contracts::CoreInstructionReplayFilter; +pub use self::contracts::CoreInstructionReplayFilter; /// Core instruction SQL-like row contract. -pub use crate::contracts::CoreInstructionRow; +pub use self::contracts::CoreInstructionRow; /// Core log insert contract. -pub use crate::contracts::CoreLogInsert; +pub use self::contracts::CoreLogInsert; /// Core log SQL-like row contract. -pub use crate::contracts::CoreLogRow; +pub use self::contracts::CoreLogRow; /// Core transaction insert contract. -pub use crate::contracts::CoreTransactionInsert; +pub use self::contracts::CoreTransactionInsert; /// Core transaction SQL-like row contract. -pub use crate::contracts::CoreTransactionRow; +pub use self::contracts::CoreTransactionRow; /// Core Solana storage behavior. -pub use crate::contracts::CoreTransactionStore; +pub use self::contracts::CoreTransactionStore; /// Default repository page size. -pub use crate::contracts::DEFAULT_PAGE_SIZE; +pub use self::contracts::DEFAULT_PAGE_SIZE; /// One machine-readable decoder coverage declaration row. -pub use crate::contracts::DecodeCoverageDeclarationInsert; +pub use self::contracts::DecodeCoverageDeclarationInsert; /// One observed coverage classification row owned by one decode attempt. -pub use crate::contracts::DecodeCoverageObservationInsert; +pub use self::contracts::DecodeCoverageObservationInsert; /// One row of aggregated decoder coverage diagnostics. -pub use crate::contracts::DecodeCoverageSummaryRow; +pub use self::contracts::DecodeCoverageSummaryRow; /// Failed decode attempt persisted in the common ledger. -pub use crate::contracts::DecodeFailure; +pub use self::contracts::DecodeFailure; /// One processor-owned decoded observation row. -pub use crate::contracts::DecodeObservationInsert; +pub use self::contracts::DecodeObservationInsert; /// Atomic persistence bundle for one decoder and one contextual input. -pub use crate::contracts::DecodePersistenceBundle; +pub use self::contracts::DecodePersistenceBundle; /// Contextual instruction decode and materialization storage behavior. -pub use crate::contracts::DecodePipelineStore; +pub use self::contracts::DecodePipelineStore; /// Bounded contextual instruction selection filter for decode campaigns. -pub use crate::contracts::DecodeSelectionFilter; +pub use self::contracts::DecodeSelectionFilter; /// Decoded event insert contract. -pub use crate::contracts::DecodedEventInsert; +pub use self::contracts::DecodedEventInsert; /// Decoded event SQL-like row contract. -pub use crate::contracts::DecodedEventRow; +pub use self::contracts::DecodedEventRow; /// Decoded event storage behavior. -pub use crate::contracts::DecodedEventStore; +pub use self::contracts::DecodedEventStore; /// Insert or upsert result contract returned by repositories. -pub use crate::contracts::InsertOutcome; +pub use self::contracts::InsertOutcome; /// Maximum number of materialized rows returned by one bounded query. -pub use crate::contracts::MAX_MATERIALIZED_EVENT_QUERY_ROWS; +pub use self::contracts::MAX_MATERIALIZED_EVENT_QUERY_ROWS; /// Maximum repository page size. -pub use crate::contracts::MAX_PAGE_SIZE; +pub use self::contracts::MAX_PAGE_SIZE; /// Atomic persistence bundle for one materializer and one decoded observation. -pub use crate::contracts::MaterializationPersistenceBundle; +pub use self::contracts::MaterializationPersistenceBundle; /// Bounded read-only materialized event selection. -pub use crate::contracts::MaterializedEventFilter; +pub use self::contracts::MaterializedEventFilter; /// Materialized event insert contract. -pub use crate::contracts::MaterializedEventInsert; +pub use self::contracts::MaterializedEventInsert; /// One materialized output returned by a bounded query. -pub use crate::contracts::MaterializedEventQueryRow; +pub use self::contracts::MaterializedEventQueryRow; /// Materialized event SQL-like row contract. -pub use crate::contracts::MaterializedEventRow; +pub use self::contracts::MaterializedEventRow; /// Materialized event storage behavior. -pub use crate::contracts::MaterializedEventStore; +pub use self::contracts::MaterializedEventStore; /// One processor-owned materialized output row. -pub use crate::contracts::MaterializedOutputInsert; +pub use self::contracts::MaterializedOutputInsert; /// Page request contract for repository list operations. -pub use crate::contracts::PageRequest; +pub use self::contracts::PageRequest; /// Stable processing ledger identity. -pub use crate::contracts::ProcessingLedgerIdentity; +pub use self::contracts::ProcessingLedgerIdentity; /// Processing ledger mark request contract. -pub use crate::contracts::ProcessingLedgerMark; +pub use self::contracts::ProcessingLedgerMark; /// Processing ledger SQL-like row contract. -pub use crate::contracts::ProcessingLedgerRow; +pub use self::contracts::ProcessingLedgerRow; /// Stable processing ledger status. -pub use crate::contracts::ProcessingLedgerStatus; +pub use self::contracts::ProcessingLedgerStatus; /// Processing ledger storage behavior. -pub use crate::contracts::ProcessingLedgerStore; +pub use self::contracts::ProcessingLedgerStore; /// Program observation storage behavior. -pub use crate::contracts::ProgramObservationStore; +pub use self::contracts::ProgramObservationStore; /// Raw payload lifecycle mark request. -pub use crate::contracts::RawPayloadLifecycleMark; +pub use self::contracts::RawPayloadLifecycleMark; /// Raw payload processing state. -pub use crate::contracts::RawPayloadProcessingState; +pub use self::contracts::RawPayloadProcessingState; /// Raw payload retention state. -pub use crate::contracts::RawPayloadRetentionState; +pub use self::contracts::RawPayloadRetentionState; /// Canonical raw Solana transaction insert contract. -pub use crate::contracts::RawTransactionInsert; +pub use self::contracts::RawTransactionInsert; /// Canonical raw Solana transaction SQL-like row contract. -pub use crate::contracts::RawTransactionRow; +pub use self::contracts::RawTransactionRow; /// Raw transaction storage behavior. -pub use crate::contracts::RawTransactionStore; +pub use self::contracts::RawTransactionStore; /// Sort direction for repository list operations. -pub use crate::contracts::SortDirection; +pub use self::contracts::SortDirection; /// Store backend diagnostic contract. -pub use crate::contracts::StoreBackendDescriptor; +pub use self::contracts::StoreBackendDescriptor; /// Store backend kind contract. -pub use crate::contracts::StoreBackendKind; +pub use self::contracts::StoreBackendKind; /// Store backend health snapshot. -pub use crate::contracts::StoreHealthSnapshot; +pub use self::contracts::StoreHealthSnapshot; /// Store backend health status. -pub use crate::contracts::StoreHealthStatus; +pub use self::contracts::StoreHealthStatus; /// Store health storage behavior. -pub use crate::contracts::StoreHealthStore; +pub use self::contracts::StoreHealthStore; /// Store migration diagnostic snapshot contract. -pub use crate::contracts::StoreMigrationSnapshot; +pub use self::contracts::StoreMigrationSnapshot; /// Store migration status contract. -pub use crate::contracts::StoreMigrationStatus; +pub use self::contracts::StoreMigrationStatus; /// Transaction acquisition observation insert contract. -pub use crate::contracts::TransactionObservationInsert; +pub use self::contracts::TransactionObservationInsert; /// Transaction acquisition observation origin. -pub use crate::contracts::TransactionObservationOrigin; +pub use self::contracts::TransactionObservationOrigin; /// Transaction acquisition observation SQL-like row contract. -pub use crate::contracts::TransactionObservationRow; +pub use self::contracts::TransactionObservationRow; /// Transaction acquisition observation status. -pub use crate::contracts::TransactionObservationStatus; +pub use self::contracts::TransactionObservationStatus; /// Storage error helper functions. -pub use crate::contracts::storage_contract_error; +pub use self::contracts::storage_contract_error; /// Allowed Solana table domains encoded in table names. -pub use crate::postgres::ALLOWED_SOLANA_TABLE_DOMAINS; +pub use self::postgres::ALLOWED_SOLANA_TABLE_DOMAINS; /// Core account key table name. -pub use crate::postgres::CORE_ACCOUNT_KEYS_TABLE_NAME; +pub use self::postgres::CORE_ACCOUNT_KEYS_TABLE_NAME; /// Core balance change table name. -pub use crate::postgres::CORE_BALANCE_CHANGES_TABLE_NAME; +pub use self::postgres::CORE_BALANCE_CHANGES_TABLE_NAME; /// Core inner instruction table name. -pub use crate::postgres::CORE_INNER_INSTRUCTIONS_TABLE_NAME; +pub use self::postgres::CORE_INNER_INSTRUCTIONS_TABLE_NAME; /// Core instruction table name. -pub use crate::postgres::CORE_INSTRUCTIONS_TABLE_NAME; +pub use self::postgres::CORE_INSTRUCTIONS_TABLE_NAME; /// Core log table name. -pub use crate::postgres::CORE_LOGS_TABLE_NAME; +pub use self::postgres::CORE_LOGS_TABLE_NAME; /// Core Solana table names. -pub use crate::postgres::CORE_STORE_TABLE_NAMES; +pub use self::postgres::CORE_STORE_TABLE_NAMES; /// Core transaction table name. -pub use crate::postgres::CORE_TRANSACTIONS_TABLE_NAME; +pub use self::postgres::CORE_TRANSACTIONS_TABLE_NAME; /// Machine-readable decoder coverage declaration table name. -pub use crate::postgres::DECODE_COVERAGE_DECLARATIONS_TABLE_NAME; +pub use self::postgres::DECODE_COVERAGE_DECLARATIONS_TABLE_NAME; /// Observed decoder coverage classification table name. -pub use crate::postgres::DECODE_COVERAGE_OBSERVATIONS_TABLE_NAME; +pub use self::postgres::DECODE_COVERAGE_OBSERVATIONS_TABLE_NAME; /// Versioned decoded event table name. -pub use crate::postgres::DECODE_EVENTS_TABLE_NAME; +pub use self::postgres::DECODE_EVENTS_TABLE_NAME; /// Decode and materialization table names. -pub use crate::postgres::DECODE_STORE_TABLE_NAMES; +pub use self::postgres::DECODE_STORE_TABLE_NAMES; /// Default PostgreSQL schema policy. -pub use crate::postgres::DEFAULT_SCHEMA_POLICY; +pub use self::postgres::DEFAULT_SCHEMA_POLICY; /// Versioned materialized output table name. -pub use crate::postgres::MATERIALIZED_EVENTS_TABLE_NAME; +pub use self::postgres::MATERIALIZED_EVENTS_TABLE_NAME; /// Maximum number of rows returned by one replay candidate query. -pub use crate::postgres::MAX_REPLAY_CANDIDATE_ROWS; +pub use self::postgres::MAX_REPLAY_CANDIDATE_ROWS; /// PostgreSQL migration strategy used by this crate. -pub use crate::postgres::MIGRATION_STRATEGY; +pub use self::postgres::MIGRATION_STRATEGY; /// Migration table name used by sqlx. -pub use crate::postgres::MIGRATION_TABLE_NAME; +pub use self::postgres::MIGRATION_TABLE_NAME; /// Processing ledger table name. -pub use crate::postgres::PROCESSING_LEDGER_TABLE_NAME; +pub use self::postgres::PROCESSING_LEDGER_TABLE_NAME; /// PostgreSQL diagnostic snapshot. -pub use crate::postgres::PostgresBackendDiagnostics; +pub use self::postgres::PostgresBackendDiagnostics; /// Bounded read-only filter for core entity summaries. -pub use crate::postgres::PostgresReplayEntityFilter; +pub use self::postgres::PostgresReplayEntityFilter; /// Core entity kind used while filtering replay candidates. -pub use crate::postgres::PostgresReplayEntityKind; +pub use self::postgres::PostgresReplayEntityKind; /// Aggregated mint, owner or account-key occurrences from core tables. -pub use crate::postgres::PostgresReplayEntitySummary; +pub use self::postgres::PostgresReplayEntitySummary; /// Bounded read-only filter for program summaries. -pub use crate::postgres::PostgresReplayProgramFilter; +pub use self::postgres::PostgresReplayProgramFilter; /// Program occurrence scope used while filtering replay candidates. -pub use crate::postgres::PostgresReplayProgramScope; +pub use self::postgres::PostgresReplayProgramScope; /// Aggregated program occurrences across outer, inner and linked logs. -pub use crate::postgres::PostgresReplayProgramSummary; +pub use self::postgres::PostgresReplayProgramSummary; /// One raw transaction candidate enriched with core and ledger diagnostics. -pub use crate::postgres::PostgresReplayTransactionCandidate; +pub use self::postgres::PostgresReplayTransactionCandidate; /// Bounded read-only filter for transaction replay candidates. -pub use crate::postgres::PostgresReplayTransactionFilter; +pub use self::postgres::PostgresReplayTransactionFilter; /// PostgreSQL store handle. -pub use crate::postgres::PostgresStore; +pub use self::postgres::PostgresStore; /// PostgreSQL store connection options. -pub use crate::postgres::PostgresStoreOptions; +pub use self::postgres::PostgresStoreOptions; /// PostgreSQL diagnostic table specification. -pub use crate::postgres::PostgresTableDiagnosticSpec; +pub use self::postgres::PostgresTableDiagnosticSpec; /// PostgreSQL table diagnostic snapshot. -pub use crate::postgres::PostgresTableDiagnostics; +pub use self::postgres::PostgresTableDiagnostics; /// PostgreSQL table statistics snapshot. -pub use crate::postgres::PostgresTableStatistics; +pub use self::postgres::PostgresTableStatistics; /// Canonical transaction acquisition table names. -pub use crate::postgres::RAW_STORE_TABLE_NAMES; +pub use self::postgres::RAW_STORE_TABLE_NAMES; /// Canonical raw transaction table name. -pub use crate::postgres::RAW_TRANSACTIONS_TABLE_NAME; +pub use self::postgres::RAW_TRANSACTIONS_TABLE_NAME; /// Solana application table prefix. -pub use crate::postgres::SOLANA_TABLE_PREFIX; +pub use self::postgres::SOLANA_TABLE_PREFIX; /// Advisory lock id used while initializing store tables. -pub use crate::postgres::STORE_SCHEMA_ADVISORY_LOCK_ID; +pub use self::postgres::STORE_SCHEMA_ADVISORY_LOCK_ID; /// Transaction acquisition observation table name. -pub use crate::postgres::TRANSACTION_OBSERVATIONS_TABLE_NAME; +pub use self::postgres::TRANSACTION_OBSERVATIONS_TABLE_NAME; /// Core store SQL statements applied by the idempotent initializer. -pub use crate::postgres::core_store_schema_statements; +pub use self::postgres::core_store_schema_statements; /// Core table diagnostic specs. -pub use crate::postgres::core_store_table_diagnostic_specs; +pub use self::postgres::core_store_table_diagnostic_specs; /// Decode and materialization SQL statements applied by the idempotent initializer. -pub use crate::postgres::decode_store_schema_statements; +pub use self::postgres::decode_store_schema_statements; /// Decode and materialization table diagnostic specs. -pub use crate::postgres::decode_store_table_diagnostic_specs; +pub use self::postgres::decode_store_table_diagnostic_specs; /// Returns true when a Solana table name follows canonical rules. -pub use crate::postgres::is_valid_solana_table_name; +pub use self::postgres::is_valid_solana_table_name; /// Returns a DSN masked for logs and UI diagnostics. -pub use crate::postgres::mask_postgres_dsn; +pub use self::postgres::mask_postgres_dsn; /// Canonical transaction acquisition SQL statements. -pub use crate::postgres::raw_store_schema_statements; +pub use self::postgres::raw_store_schema_statements; /// Canonical transaction acquisition diagnostic specs. -pub use crate::postgres::raw_store_table_diagnostic_specs; +pub use self::postgres::raw_store_table_diagnostic_specs; /// Validates core store table names. -pub use crate::postgres::validate_core_store_table_names; +pub use self::postgres::validate_core_store_table_names; /// Validates decode and materialization store table names. -pub use crate::postgres::validate_decode_store_table_names; +pub use self::postgres::validate_decode_store_table_names; /// Validates canonical transaction acquisition table names. -pub use crate::postgres::validate_raw_store_table_names; +pub use self::postgres::validate_raw_store_table_names; /// Validates a canonical Solana table name. -pub use crate::postgres::validate_solana_table_name; +pub use self::postgres::validate_solana_table_name; /// Current normalized core replay input contract version. -pub use kb_lib::CORE_REPLAY_INPUT_CONTRACT_VERSION; +pub use kb_lib::MD_CORE_REPLAY_INPUT_CONTRACT_VERSION; /// Decoder replay input containing one instruction plus extracted transaction context. -pub use kb_lib::CoreInstructionReplayInput; +pub use kb_lib::MdCoreInstructionReplayInput; diff --git a/kb-store/src/postgres/query/core_queries.rs b/kb-store/src/postgres/query/core_queries.rs index 136c3d8..f25c825 100644 --- a/kb-store/src/postgres/query/core_queries.rs +++ b/kb-store/src/postgres/query/core_queries.rs @@ -372,7 +372,7 @@ pub(in crate::postgres) async fn list_core_instruction_replay_inputs( pool: &sqlx::PgPool, filter: &crate::CoreInstructionReplayFilter, page_request: &crate::PageRequest, -) -> kb_core::Result> { +) -> kb_core::Result> { let instructions_result = crate::postgres::query::core_queries::list_core_instructions_for_replay( pool, @@ -402,7 +402,7 @@ pub(in crate::postgres) async fn list_core_instruction_replay_inputs( pub(in crate::postgres) async fn list_decode_replay_inputs( pool: &sqlx::PgPool, filter: &crate::DecodeSelectionFilter, -) -> kb_core::Result> { +) -> kb_core::Result> { let min_slot_result = crate::postgres::query::core_queries::optional_sql_slot_from_u64(filter.min_slot); let min_slot = match min_slot_result { @@ -758,7 +758,7 @@ where pub(in crate::postgres) async fn load_replay_input_for_instruction( pool: &sqlx::PgPool, instruction: &crate::CoreInstructionRow, -) -> kb_core::Result { +) -> kb_core::Result { let transaction_context_result = sqlx::query_as::)>( "SELECT failed, err_json FROM kb_sol_core_transactions WHERE signature = $1 LIMIT 1", @@ -830,7 +830,7 @@ pub(in crate::postgres) async fn load_replay_input_for_instruction( std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - return crate::CoreInstructionReplayInput::new( + return crate::MdCoreInstructionReplayInput::new( replay_input_key, instruction.signature.clone(), slot, diff --git a/kb-store/src/postgres/query/decode_pipeline_queries.rs b/kb-store/src/postgres/query/decode_pipeline_queries.rs index 2fd8851..469cea9 100644 --- a/kb-store/src/postgres/query/decode_pipeline_queries.rs +++ b/kb-store/src/postgres/query/decode_pipeline_queries.rs @@ -69,7 +69,7 @@ pub(in crate::postgres) async fn apply_decode_store_schema( pub(in crate::postgres) async fn list_decode_inputs( pool: &sqlx::PgPool, filter: &crate::DecodeSelectionFilter, -) -> kb_core::Result> { +) -> kb_core::Result> { tracing::debug!(target: crate::TRACING_TARGET, action = "list_decode_inputs", signature_count = filter.signatures.len(), signature_sample = ?filter.signatures.iter().take(5).map(std::string::String::as_str).collect::>(), processing_states = ?filter.processing_states, min_slot = ?filter.min_slot, max_slot = ?filter.max_slot, program_ids = ?filter.program_ids, instruction_paths = ?filter.instruction_paths, limit = filter.limit, "query PostgreSQL contextual decode inputs"); let result = crate::postgres::query::core_queries::list_decode_replay_inputs(pool, filter).await; diff --git a/kb-store/src/postgres/query/raw_queries.rs b/kb-store/src/postgres/query/raw_queries.rs index 80d7d2b..2ebc134 100644 --- a/kb-store/src/postgres/query/raw_queries.rs +++ b/kb-store/src/postgres/query/raw_queries.rs @@ -420,7 +420,7 @@ mod tests { assert_eq!(duplicate_outcome.skipped_count, 1); let has_result = crate::RawTransactionStore::has_raw_transaction_signature( &store, - &kb_lib::Signature(signature.clone()), + &kb_lib::MdSignature(signature.clone()), ) .await; let has_signature = match has_result { diff --git a/kb-store/src/postgres/repository/core_transaction_repository.rs b/kb-store/src/postgres/repository/core_transaction_repository.rs index 146f047..4e4ff84 100644 --- a/kb-store/src/postgres/repository/core_transaction_repository.rs +++ b/kb-store/src/postgres/repository/core_transaction_repository.rs @@ -96,7 +96,7 @@ impl crate::CoreTransactionStore for crate::PostgresStore { &self, filter: &crate::CoreInstructionReplayFilter, page_request: &crate::PageRequest, - ) -> kb_core::Result> { + ) -> kb_core::Result> { return crate::postgres::query::list_core_instruction_replay_inputs( self.pool(), filter, diff --git a/kb-store/src/postgres/repository/decode_pipeline_repository.rs b/kb-store/src/postgres/repository/decode_pipeline_repository.rs index 0a947b1..489d668 100644 --- a/kb-store/src/postgres/repository/decode_pipeline_repository.rs +++ b/kb-store/src/postgres/repository/decode_pipeline_repository.rs @@ -12,7 +12,7 @@ impl crate::DecodePipelineStore for crate::PostgresStore { async fn list_decode_inputs( &self, filter: &crate::DecodeSelectionFilter, - ) -> kb_core::Result> { + ) -> kb_core::Result> { return crate::postgres::query::list_decode_inputs(self.pool(), filter).await; } diff --git a/kb-store/src/postgres/repository/raw_transaction_repository.rs b/kb-store/src/postgres/repository/raw_transaction_repository.rs index e98abee..f7a0cde 100644 --- a/kb-store/src/postgres/repository/raw_transaction_repository.rs +++ b/kb-store/src/postgres/repository/raw_transaction_repository.rs @@ -11,7 +11,7 @@ impl crate::RawTransactionStore for crate::PostgresStore { )] async fn has_raw_transaction_signature( &self, - signature: &kb_lib::Signature, + signature: &kb_lib::MdSignature, ) -> kb_core::Result { return crate::postgres::query::has_raw_transaction_signature( self.pool(), diff --git a/khadhroony-bot3_v0.1.0-pre.010-full-modified.zip b/khadhroony-bot3_v0.1.0-pre.010-full-modified.zip new file mode 100644 index 0000000..2f136a6 Binary files /dev/null and b/khadhroony-bot3_v0.1.0-pre.010-full-modified.zip differ diff --git a/migration/khadhroony-bot2-reference/CHANGELOG.md b/migration/khadhroony-bot2-reference/CHANGELOG.md index b08dcc6..9414f72 100644 --- a/migration/khadhroony-bot2-reference/CHANGELOG.md +++ b/migration/khadhroony-bot2-reference/CHANGELOG.md @@ -35,7 +35,7 @@ Validation du jalon de cadrage stockage : conventions PostgreSQL définies autou ## 0.2.1 — contrats `kb_store_core` et replay instruction-level -Validation du jalon de contrats storage : `kb_store_core` expose les types communs backend-agnostiques pour pagination, healthcheck, migrations, erreurs de stockage, DTOs applicatifs, entities proches SQL et traits repositories sans implémentation PostgreSQL. Les contrats couvrent le raw RPC et WebSocket, le cycle de vie raw `Full` / `Compacted` / `Archived` / `Purged`, les états de traitement raw, la signature optionnelle des notifications WebSocket, la déduplication par `notification_key`, le lien futur optionnel notification vers transaction canonique, ainsi que le replay par instruction. Le replay est défini comme un scheduling au niveau instruction, mais le décodage reçoit un contexte extrait complet via `CoreInstructionReplayInput` : instruction ciblée, account keys, logs, balance changes et contexte transactionnel minimal. Les repositories restent abstraits et ne créent encore ni pool PostgreSQL, ni migration SQL réelle. Validation locale effectuée : `cargo test -p kb_store_core` avec 28 tests passés et `cargo clippy --all-targets` sans avertissement. Les validations précédentes du jalon ont également confirmé `kb_store_pg` sans test actif, `kb_config` avec 35 tests passés et `kb_app_demo` avec 28 tests passés. +Validation du jalon de contrats storage : `kb_store_core` expose les types communs backend-agnostiques pour pagination, healthcheck, migrations, erreurs de stockage, DTOs applicatifs, entities proches SQL et traits repositories sans implémentation PostgreSQL. Les contrats couvrent le raw RPC et WebSocket, le cycle de vie raw `Full` / `Compacted` / `Archived` / `Purged`, les états de traitement raw, la signature optionnelle des notifications WebSocket, la déduplication par `notification_key`, le lien futur optionnel notification vers transaction canonique, ainsi que le replay par instruction. Le replay est défini comme un scheduling au niveau instruction, mais le décodage reçoit un contexte extrait complet via `MdCoreInstructionReplayInput` : instruction ciblée, account keys, logs, balance changes et contexte transactionnel minimal. Les repositories restent abstraits et ne créent encore ni pool PostgreSQL, ni migration SQL réelle. Validation locale effectuée : `cargo test -p kb_store_core` avec 28 tests passés et `cargo clippy --all-targets` sans avertissement. Les validations précédentes du jalon ont également confirmé `kb_store_pg` sans test actif, `kb_config` avec 35 tests passés et `kb_app_demo` avec 28 tests passés. ## 0.2.2 — infrastructure PostgreSQL minimale @@ -47,7 +47,7 @@ Validation du jalon raw store minimal : `kb_store_pg` crée et initialise les de ## 0.2.4 — core Solana normalisé minimal -Validation du jalon core store minimal : `kb_store_pg` crée et initialise maintenant les tables core `kb_sol_core_transactions`, `kb_sol_core_account_keys`, `kb_sol_core_instructions`, `kb_sol_core_inner_instructions`, `kb_sol_core_logs` et `kb_sol_core_balance_changes`, en complément du raw store `0.2.3`, sans schema PostgreSQL applicatif explicite. Les migrations et l'initializer utilisent des noms SQL préfixés et explicites pour les contraintes et index : `pk_`, `fk_`, `ck_`, `ux_` et `ix_`. L'initialisation raw/core est sérialisée par un verrou PostgreSQL `pg_advisory_xact_lock` afin d'éviter les courses concurrentes pendant les tests ou les démarrages parallèles. `CoreTransactionStore` dispose de l'implémentation PostgreSQL minimale pour insérer les transactions core, account keys, instructions, inner instructions, logs et deltas de balances, puis reconstruire `CoreInstructionReplayInput` pour les futurs décodeurs. Le script de maintenance `kb_store_pg/maintenance/drop_raw_core_store.sql` permet de réinitialiser explicitement les tables raw/core locales dans l'ordre inverse des dépendances. Validation locale effectuée : `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana cargo test -p kb_store_pg -- --nocapture` avec 30 tests passés, création vérifiée des 8 tables dans PostgreSQL, réinitialisation validée via le script de maintenance, puis `cargo clippy --all-targets` sans avertissement. Le worker d'extraction raw RPC vers core, les observations et le ledger ops sont conservés pour les jalons suivants. +Validation du jalon core store minimal : `kb_store_pg` crée et initialise maintenant les tables core `kb_sol_core_transactions`, `kb_sol_core_account_keys`, `kb_sol_core_instructions`, `kb_sol_core_inner_instructions`, `kb_sol_core_logs` et `kb_sol_core_balance_changes`, en complément du raw store `0.2.3`, sans schema PostgreSQL applicatif explicite. Les migrations et l'initializer utilisent des noms SQL préfixés et explicites pour les contraintes et index : `pk_`, `fk_`, `ck_`, `ux_` et `ix_`. L'initialisation raw/core est sérialisée par un verrou PostgreSQL `pg_advisory_xact_lock` afin d'éviter les courses concurrentes pendant les tests ou les démarrages parallèles. `CoreTransactionStore` dispose de l'implémentation PostgreSQL minimale pour insérer les transactions core, account keys, instructions, inner instructions, logs et deltas de balances, puis reconstruire `MdCoreInstructionReplayInput` pour les futurs décodeurs. Le script de maintenance `kb_store_pg/maintenance/drop_raw_core_store.sql` permet de réinitialiser explicitement les tables raw/core locales dans l'ordre inverse des dépendances. Validation locale effectuée : `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana cargo test -p kb_store_pg -- --nocapture` avec 30 tests passés, création vérifiée des 8 tables dans PostgreSQL, réinitialisation validée via le script de maintenance, puis `cargo clippy --all-targets` sans avertissement. Le worker d'extraction raw RPC vers core, les observations et le ledger ops sont conservés pour les jalons suivants. ## 0.2.5 — diagnostics SQL PostgreSQL dans `kb_app_demo` diff --git a/migration/khadhroony-bot2-reference/ROADMAP.md b/migration/khadhroony-bot2-reference/ROADMAP.md index f21cd46..a49aa0b 100644 --- a/migration/khadhroony-bot2-reference/ROADMAP.md +++ b/migration/khadhroony-bot2-reference/ROADMAP.md @@ -172,7 +172,7 @@ Ce fichier contient les changements futurs et le phasage prévu. Il ne remplace - [x] Ajouter les types communs : pagination, tri, limites, healthcheck, statut migration. - [x] Ajouter les premiers DTO génériques : raw RPC transaction, raw WS notification, core transaction, core instruction. - [x] Ajouter les contrats core pour account keys, logs et balance changes extraits. -- [x] Ajouter `CoreInstructionReplayInput` pour fournir aux décodeurs une instruction avec contexte extrait. +- [x] Ajouter `MdCoreInstructionReplayInput` pour fournir aux décodeurs une instruction avec contexte extrait. - [x] Ajouter les contrats de cycle de vie raw : état de rétention, état de traitement et mark lifecycle. - [x] Ajouter les contrats de replay par instruction : état instruction, filtre de replay et lifecycle mark. - [x] Ajouter les premiers traits repository sans implémentation SQL. @@ -229,7 +229,7 @@ Ce fichier contient les changements futurs et le phasage prévu. Il ne remplace ### 0.2.4 — core Solana normalisé minimal - [x] Créer les tables core minimales : `kb_sol_core_transactions`, `kb_sol_core_account_keys`, `kb_sol_core_instructions`, `kb_sol_core_inner_instructions`, `kb_sol_core_logs`, `kb_sol_core_balance_changes`. -- [x] Construire `CoreInstructionReplayInput` depuis les tables `core` pour les décodeurs. +- [x] Construire `MdCoreInstructionReplayInput` depuis les tables `core` pour les décodeurs. - [x] Marquer les instructions insérées comme `Pending` pour permettre un replay instruction-level. - [x] Préparer le replay partiel par état, slot et program id via `CoreInstructionReplayFilter`. - [x] Ajouter une initialisation idempotente raw/core via `PostgresStore::initialize_store_schema()`. @@ -460,7 +460,7 @@ Les contrôles autrefois prévus dans `0.3.5` sont reclassés ainsi : la stabili - [x] Auditer les crates utilisant `tracing.workspace = true` et couvrir les treize crates alors actives par un test de constante canonique et par les routes des trois profils. - [x] Ajouter le tracing propriétaire manquant sur les clients/pools HTTP et WebSocket ainsi que sur le backfill ; promouvoir les inputs decode unmatched, statuts failed/unsupported et échecs de matérialisation/persistance au niveau `error`. - [x] Formaliser dans `docs/SOLANA_INTERFACE_DEPENDENCIES.md` la politique d’interfaces officielles : dépendance seulement au point de consommation, priorité `wincode` puis Borsh, parser borné lorsque l’interface n’expose que `bincode`. -- [x] Passer `CoreInstructionReplayInput` au contrat `2` avec une liste stable et numériquement ordonnée des instructions outer, sans migration SQL, afin de résoudre les références inter-instructions des précompiles. +- [x] Passer `MdCoreInstructionReplayInput` au contrat `2` avec une liste stable et numériquement ordonnée des instructions outer, sans migration SQL, afin de résoudre les références inter-instructions des précompiles. - [x] Décoder `zk_elgamal_proof` dans `pre.015` selon `solana-zk-elgamal-proof-interface ^0.1` et le runtime Agave : treize discriminants, preuves inline ou référencées par compte, contexte optionnel et fermeture du contexte, sans recalcul cryptographique. - [x] Décoder dans `pre.016` l’ancien `zk_token_proof` comme compatibilité historique, puis retirer dans `pre.019` la dépendance dépréciée `solana-zk-token-sdk` au profit d’un miroir wire local borné des dix-sept discriminants et tailles auditées. - [x] Décoder les loaders `native_loader`, `bpf_loader_deprecated`, `bpf_loader`, `bpf_loader_upgradeable` et `loader_v4` ; classer l’invocation Native Loader opaque comme `ignored` sans sémantique inventée. @@ -532,14 +532,14 @@ Les contrôles autrefois prévus dans `0.3.5` sont reclassés ainsi : la stabili #### Suite d’orchestration -- [x] `pre.004` : ajouter dans `kb_rpc` les adaptateurs typés `getGenesisHash`, `getLatestBlockhash`, `getFeeForMessage` et `simulateTransaction`, avec routage par rôle, classification des clusters publics, diagnostics runtime et conversion vers `ExecutionSimulationResult`, sans signature ni envoi. +- [x] `pre.004` : ajouter dans `kb_rpc` les adaptateurs typés `getGenesisHash`, `getLatestBlockhash`, `getFeeForMessage` et `simulateTransaction`, avec routage par rôle, classification des clusters publics, diagnostics runtime et conversion vers `ExApiExecutionSimulationResult`, sans signature ni envoi. - [x] `pre.004` : documenter dans `kb_executor_solana_core/README.md` chaque fonction publique, les six opérations constructibles, leurs paramètres, résultats, effets et frontières. - [x] Valider localement `pre.004` : `kb_rpc` 63 tests, `kb_execution_api` 21 tests, `kb_execution_safety` 13 tests, `kb_executor_solana_core` 10 tests, `kb_config` 40 tests et Clippy global propre. - [x] `pre.005` : ajouter `kb_execution_solana` pour assembler les instructions planifiées en transaction legacy, produire les payloads base64 de frais/simulation, lier la simulation au hash exact du message, résoudre exactement les signataires requis via l’interface Solana `Signer` et signer séparément hors Tauri. - [x] `pre.005` : renommer la constante interne en `MAINNET_GENESIS_HASH` sans changer sa valeur ; conserver `mainnet-beta` seulement comme alias historique des endpoints/CLI et renommer le variant public en `Mainnet` sérialisé `mainnet`. - [x] `pre.005` : distinguer la simulation exacte de la simulation avec remplacement de blockhash et interdire qu’un résultat `replaceRecentBlockhash=true` autorise la signature du message original. - [x] Valider localement les tests ciblés de `pre.005`/`pre.006` : `kb_execution_solana` 7 tests, `kb_execution_api` 22 tests, `kb_execution_safety` 15 tests, `kb_rpc` 63 tests, `kb_executor_solana_core` 10 tests, `kb_wallet` 6 tests et `kb_config` 40 tests. -- [x] `pre.006` : corriger la compilation croisée de `pre.005`, supprimer l’avertissement TS-rs sur l’alias historique `mainnet_beta`, utiliser le trait public `TypedInstructionExecutor` dans les tests d’assemblage, resynchroniser le contrat de simulation RPC et rendre les erreurs de routage tracing explicites. +- [x] `pre.006` : corriger la compilation croisée de `pre.005`, supprimer l’avertissement TS-rs sur l’alias historique `mainnet_beta`, utiliser le trait public `ExApiTypedInstructionExecutor` dans les tests d’assemblage, resynchroniser le contrat de simulation RPC et rendre les erreurs de routage tracing explicites. - [x] `pre.007` : supprimer le dernier opérateur `?` introduit dans un chemin de production de `kb_execution_api`, le remplacer par un `match` avec propagation explicite et auditer les fichiers d’exécution `0.4.2` contre `?`, `unwrap` et `expect` de production. - [x] Valider localement `pre.007` : `kb_execution_api` 22 tests et Clippy global propre. - [x] `pre.008` : ajouter les contrats RPC typés `getBalance`, `requestAirdrop`, `sendTransaction`, `getSignatureStatuses` et `getBlockHeight`, avec routage par rôle, préflight obligatoire, contrôle de la signature retournée et confirmation bornée jusqu’à succès, échec, expiration ou timeout. @@ -603,7 +603,7 @@ Les contrôles autrefois prévus dans `0.3.5` sont reclassés ainsi : la stabili - [x] Valider localement `pre.019` : `kb_executor_solana_core` 70 tests, `kb_execution_api` 22, `kb_execution_safety` 15, `kb_execution_solana` 12, `kb_rpc` 70 et Clippy global propre. - [x] `pre.020` : onze opérations Loader v3 et neuf opérations Loader v4 réellement constructibles, avec déploiement/upgrade/autorités/fermeture hors UI; BPF Loader v1/v2 restent historiques `decode-only` et Native Loader est classé sans instruction client. - [x] Valider localement `pre.020` : `kb_executor_solana_core` 81 tests, `kb_decoder_solana_core` 115, `kb_execution_api` 22, `kb_execution_safety` 15, `kb_execution_solana` 12 et `kb_rpc` 70. -- [x] `pre.021` : centraliser dans un module privé les parsers `Pubkey`/program ID et les validations communes de longueur, montant positif, comptes distincts, dérivation seedée et erreurs partagées ; supprimer les implémentations de production identiques sans modifier les 109 opérations ni leur wire. +- [x] `pre.021` : centraliser dans un module privé les parsers `MdPubkey`/program ID et les validations communes de longueur, montant positif, comptes distincts, dérivation seedée et erreurs partagées ; supprimer les implémentations de production identiques sans modifier les 109 opérations ni leur wire. - [x] Valider localement `pre.021` après `fix.001` : `kb_executor_solana_core` 86 tests et `cargo clippy --all-targets` propre ; ce Clippy couvre également les changements Loader de `pre.020`. - [x] `pre.022` : implémenter le préflight stateful Localnet/Devnet pour ALT, Config, Feature, Slashing et contextes ZK ElGamal ; ajouter `getEpochInfo` typé et la matrice machine-readable complète des 18 surfaces natives avec classification de toute opération non invocable. - [x] Valider localement `pre.022` : `kb_executor_solana_core` 87 tests, `kb_pipeline` 56 tests, `kb_rpc` 71 tests, `kb_execution_api` 22 tests, `kb_execution_safety` 15 tests, `kb_execution_solana` 12 tests, validateur de matrice réussi et `cargo clippy --all-targets` propre. diff --git a/migration/khadhroony-bot2-reference/RULES.md b/migration/khadhroony-bot2-reference/RULES.md index e0aeec2..245e53a 100644 --- a/migration/khadhroony-bot2-reference/RULES.md +++ b/migration/khadhroony-bot2-reference/RULES.md @@ -138,7 +138,7 @@ Aucun renommage massif de crates n'est autorisé sans étape de contrôle dédi - Une crate est opérationnelle lorsqu’elle effectue des I/O, orchestre un pipeline, décode, matérialise, exécute, applique une politique runtime ou prend une décision mutable observable. - Toute crate opérationnelle ajoutée ou modifiée doit dépendre de `tracing` depuis le workspace et déclarer exactement un `pub(crate) const TRACING_TARGET` dans `src/constants.rs`. -- La valeur canonique de `TRACING_TARGET` est le nom exact du package Cargo. Les targets historiques `khbot.*`, les suffixes de module et les targets de fenêtre sont interdits dans les nouvelles modifications. +- La valeur canonique de `DC_METADATA_MTM_TRACING_TARGET` est le nom exact du package Cargo. Les targets historiques `khbot.*`, les suffixes de module et les targets de fenêtre sont interdits dans les nouvelles modifications. - Les macros `tracing` doivent utiliser `target: crate::TRACING_TARGET` et des champs structurés stables. La granularité interne passe par `action`, `stage`, `window`, `campaign_id`, `signature`, `instruction_path`, `program_id`, `processor_name`, `processor_version`, `status` et `error_code`. - Les crates passives de types, contrats, DTO, API sans exécution, registres ou constantes restent sans dépendance `tracing`. `kb_config` reste une exception de bootstrap tant que sa validation précède l’installation du subscriber. - Il est interdit d’ajouter `tracing` sans événement réel ou de conserver un faux target uniquement consommé par `let _target`. @@ -150,14 +150,14 @@ Aucun renommage massif de crates n'est autorisé sans étape de contrôle dédi - Chaque profil doit router les événements vers les sorties globales `debug.log`, `info.log`, `error.jsonl` et `app.log`, puis vers `debug.log`, `info.log` et `error.jsonl` dans un répertoire propre à chaque crate utilisant `tracing`. - L’ajout ou la suppression de `tracing.workspace = true` dans une crate impose la mise à jour simultanée de la matrice de routes, de ses tests et de `docs/TRACING_CONTRACT.md`. - Le contrat détaillé est défini dans `docs/TRACING_CONTRACT.md`. -- L’audit mécanique spécifique au projet est exécuté par `python3 scripts/audit_khadhroony_workspace_rules.py`. Il couvre notamment `TRACING_TARGET` et l’usage obligatoire de `solana_pubkey::Pubkey` à la place de `solana_address::Address`. +- L’audit mécanique spécifique au projet est exécuté par `python3 scripts/audit_khadhroony_workspace_rules.py`. Il couvre notamment `DC_METADATA_MTM_TRACING_TARGET` et l’usage obligatoire de `solana_pubkey::Pubkey` à la place de `solana_address::Address`. ## Règles de réutilisation des interfaces Solana et SPL - Les dépendances déclarées dans `[workspace.dependencies]` forment un catalogue de versions et de features autorisées ; elles ne doivent être ajoutées à une crate consommatrice que lorsqu’un type, un encodeur, un décodeur ou un identifiant officiel est réellement utilisé. - Dans un `Cargo.toml`, placer dans `[dependencies]` toute crate référencée par le code de bibliothèque compilé en production. Réserver `[dev-dependencies]` aux références contenues exclusivement dans `#[cfg(test)]`, les tests d’intégration, benches ou exemples. Une dépendance de test vers un décodeur ou matérialiseur concret est légitime lorsqu’elle sert uniquement à éprouver une orchestration générique fondée sur les traits API ; elle ne prouve pas qu’une capacité de production manque. Toute promotion de `dev-dependencies` vers `dependencies` doit être motivée par un appel runtime réel, et toute dépendance runtime inutilisée doit être supprimée. -- Les registres de composition runtime des applications doivent énumérer explicitement chaque décodeur et matérialiseur concret activé. Toute nouvelle surface instructionnelle dotée d’un `EventMaterializer` doit être ajoutée au registre applicatif et couverte par un test d’inventaire ordonné ; une crate présente dans le workspace ou dans `kb_pipeline` n’est pas activée automatiquement. Les matérialiseurs exclusivement stateful qui n’implémentent pas `EventMaterializer` restent routés par leurs APIs de snapshots dédiées. +- Les registres de composition runtime des applications doivent énumérer explicitement chaque décodeur et matérialiseur concret activé. Toute nouvelle surface instructionnelle dotée d’un `MtApiEventMaterializer` doit être ajoutée au registre applicatif et couverte par un test d’inventaire ordonné ; une crate présente dans le workspace ou dans `kb_pipeline` n’est pas activée automatiquement. Les matérialiseurs exclusivement stateful qui n’implémentent pas `MtApiEventMaterializer` restent routés par leurs APIs de snapshots dédiées. - Les corrélations instruction/état doivent produire une issue explicite (`confirmed`, `contradicted` ou `not_applicable`) et ne doivent jamais transformer automatiquement une configuration observée en violation, score ou conclusion métier. - Une interface officielle Solana ou SPL étroite doit être préférée à `solana-sdk` lorsque son contrat suffit. - L’ordre de préférence des formats est : schéma officiel `wincode`, schéma officiel Borsh, puis parseur local borné reproduisant exactement le runtime lorsque l’interface officielle n’expose que `bincode`. diff --git a/migration/khadhroony-bot2-reference/docs/CORE_EXTRACTION_CONTRACTS.md b/migration/khadhroony-bot2-reference/docs/CORE_EXTRACTION_CONTRACTS.md index 1a06582..22479dc 100644 --- a/migration/khadhroony-bot2-reference/docs/CORE_EXTRACTION_CONTRACTS.md +++ b/migration/khadhroony-bot2-reference/docs/CORE_EXTRACTION_CONTRACTS.md @@ -38,8 +38,8 @@ L’extraction refuse explicitement : - un `canonical_json` absent ; - un `canonical_json_hash` absent ; -- une version différente de `CANONICAL_TRANSACTION_FORMAT_VERSION` ; -- un JSON non désérialisable en `CanonicalTransaction` ; +- une version différente de `MD_CANONICAL_TRANSACTION_FORMAT_VERSION` ; +- un JSON non désérialisable en `MdCanonicalTransaction` ; - une signature ou un slot différent de la ligne raw ; - un hash recalculé différent du hash stocké ; - un indice de programme ou de compte hors de l’espace résolu. diff --git a/migration/khadhroony-bot2-reference/docs/CORE_PROGRAM_IDS.md b/migration/khadhroony-bot2-reference/docs/CORE_PROGRAM_IDS.md index 7374b9b..3745831 100644 --- a/migration/khadhroony-bot2-reference/docs/CORE_PROGRAM_IDS.md +++ b/migration/khadhroony-bot2-reference/docs/CORE_PROGRAM_IDS.md @@ -58,6 +58,6 @@ Ce fichier sépare les identifiants primitifs Solana/SPL du registre des surface | `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` | | `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` | | `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` | -| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token_2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | +| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | | `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token_2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` | | `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` | diff --git a/migration/khadhroony-bot2-reference/docs/DECODER_MATERIALIZATION_CONTRACTS.md b/migration/khadhroony-bot2-reference/docs/DECODER_MATERIALIZATION_CONTRACTS.md index a50fc64..8b428d9 100644 --- a/migration/khadhroony-bot2-reference/docs/DECODER_MATERIALIZATION_CONTRACTS.md +++ b/migration/khadhroony-bot2-reference/docs/DECODER_MATERIALIZATION_CONTRACTS.md @@ -20,7 +20,7 @@ core instruction contextualisée ## Input contextualisé -`CoreInstructionReplayInput` reste l’unique contrat d’entrée commun. Son contrat passe à la version `2` dans `0.4.1-pre.014`. Il contient la signature, le slot, le statut et l’erreur on-chain, le chemin stable de l’instruction, le program ID, les comptes résolus dans leur ordre original, le payload brut déterministe et son hash, toutes les instructions outer ordonnées par index numérique, les inner instructions descendantes, les logs reliés prudemment, les changements de balances et la version du contrat core. +`MdCoreInstructionReplayInput` reste l’unique contrat d’entrée commun. Son contrat passe à la version `2` dans `0.4.1-pre.014`. Il contient la signature, le slot, le statut et l’erreur on-chain, le chemin stable de l’instruction, le program ID, les comptes résolus dans leur ordre original, le payload brut déterministe et son hash, toutes les instructions outer ordonnées par index numérique, les inner instructions descendantes, les logs reliés prudemment, les changements de balances et la version du contrat core. `outer_instructions_json` est un tableau stable dont chaque entrée contient `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. L’instruction cible est incluse. Cette projection provient des tables core existantes et ne nécessite aucune migration SQL. @@ -30,7 +30,7 @@ Le passage au contrat `2` modifie légitimement les hashes existants, car les pa ## Contrat de décodeur -`InstructionDecoder` expose : +`DcApiInstructionDecoder` expose : - une identité stable `name/version` ; - les programmes et surfaces supportés ; @@ -58,7 +58,7 @@ observation_committed `observation_committed` doit être faux lorsque la transaction a été annulée. Ces observations peuvent décrire une instruction tentée, un événement loggé avant l’erreur, une classification d’échec, une consommation de compute ou une surface appelée. -Elles ne peuvent pas produire automatiquement un trade réussi, une modification de liquidité réussie, un changement confirmé de catalogue ou une candle normale. `EventMaterializer` applique une politique explicite par famille. Les familles `trade`, `liquidity` et `lifecycle` sont refusées avant l’appel au matérialiseur lorsque la source est échouée ou non commitée. Une seconde barrière valide ensuite les familles de sortie et n’autorise, dans ce contexte, que les matérialisations d’audit ou de risque. +Elles ne peuvent pas produire automatiquement un trade réussi, une modification de liquidité réussie, un changement confirmé de catalogue ou une candle normale. `MtApiEventMaterializer` applique une politique explicite par famille. Les familles `trade`, `liquidity` et `lifecycle` sont refusées avant l’appel au matérialiseur lorsque la source est échouée ou non commitée. Une seconde barrière valide ensuite les familles de sortie et n’autorise, dans ce contexte, que les matérialisations d’audit ou de risque. ## Persistance diff --git a/migration/khadhroony-bot2-reference/docs/EXECUTION_MODEL.md b/migration/khadhroony-bot2-reference/docs/EXECUTION_MODEL.md index 95cc292..700fd63 100644 --- a/migration/khadhroony-bot2-reference/docs/EXECUTION_MODEL.md +++ b/migration/khadhroony-bot2-reference/docs/EXECUTION_MODEL.md @@ -77,11 +77,11 @@ Le genesis hash sert à classifier les clusters publics connus. Le réseau de pr La simulation accepte une transaction base64 non signée lorsque `sigVerify = false`; `replaceRecentBlockhash = true` permet au nœud de remplacer le blockhash avant simulation. Les erreurs runtime restent un résultat de simulation typé et ne sont pas confondues avec une erreur HTTP ou JSON-RPC. -`kb_rpc` ne fabrique pas le contexte de sécurité : cluster attendu, âge du blockhash, nonce account et nonce authority sont fournis explicitement lors de la conversion vers `ExecutionSimulationResult`. Depuis `pre.013`, `getAccountInfo` possède aussi un mode données complètes borné : le mode metadata-only conserve `dataSlice.length = 0`, tandis que `confirmed_with_data(max_data_bytes)` exige un tuple base64 complet dont la longueur décodée égale `space`. +`kb_rpc` ne fabrique pas le contexte de sécurité : cluster attendu, âge du blockhash, nonce account et nonce authority sont fournis explicitement lors de la conversion vers `ExApiExecutionSimulationResult`. Depuis `pre.013`, `getAccountInfo` possède aussi un mode données complètes borné : le mode metadata-only conserve `dataSlice.length = 0`, tandis que `confirmed_with_data(max_data_bytes)` exige un tuple base64 complet dont la longueur décodée égale `space`. ## Assemblage et signature Solana -`0.4.2-pre.005` introduit `kb_execution_solana`, frontière commune entre les exécuteurs et les adaptateurs RPC. La crate convertit les `PlannedInstruction` en instructions SDK, compile le message avec son fee payer et sa source de blockhash, puis vérifie que les signataires réellement compilés correspondent exactement au contrat du plan. +`0.4.2-pre.005` introduit `kb_execution_solana`, frontière commune entre les exécuteurs et les adaptateurs RPC. La crate convertit les `ExApiPlannedInstruction` en instructions SDK, compile le message avec son fee payer et sa source de blockhash, puis vérifie que les signataires réellement compilés correspondent exactement au contrat du plan. La transaction non signée fournit deux sorties distinctes : diff --git a/migration/khadhroony-bot2-reference/docs/INSTRUCTION_REPLAY_CONTRACTS.md b/migration/khadhroony-bot2-reference/docs/INSTRUCTION_REPLAY_CONTRACTS.md index 6204d21..1a9d148 100644 --- a/migration/khadhroony-bot2-reference/docs/INSTRUCTION_REPLAY_CONTRACTS.md +++ b/migration/khadhroony-bot2-reference/docs/INSTRUCTION_REPLAY_CONTRACTS.md @@ -50,7 +50,7 @@ Certains protocoles Solana exigent de lire : - des séquences de logs liées à un CPI ; - des instructions voisines de la même transaction. -`CoreInstructionReplayInput` représente ce contrat de lecture : une instruction ciblée plus un contexte extrait depuis les tables `core`. Depuis le contrat `2`, ce contexte inclut également toutes les instructions outer de la signature, ordonnées numériquement et munies de leur payload retenu et de son hash. +`MdCoreInstructionReplayInput` représente ce contrat de lecture : une instruction ciblée plus un contexte extrait depuis les tables `core`. Depuis le contrat `2`, ce contexte inclut également toutes les instructions outer de la signature, ordonnées numériquement et munies de leur payload retenu et de son hash. ## Sélection de replay @@ -68,7 +68,7 @@ program_id = programme ciblé par le décodeur plage de slots = optionnelle ``` -Le repository charge les logs, balances, account keys et instructions outer nécessaires pour retourner `CoreInstructionReplayInput`. La liste outer inclut la cible et utilise les champs stables `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. Cette extension lit les tables existantes et ne demande aucune migration. +Le repository charge les logs, balances, account keys et instructions outer nécessaires pour retourner `MdCoreInstructionReplayInput`. La liste outer inclut la cible et utilise les champs stables `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. Cette extension lit les tables existantes et ne demande aucune migration. ## Marquage de cycle de vie diff --git a/migration/khadhroony-bot2-reference/docs/PROGRAM_REGISTRY_CONTROL.md b/migration/khadhroony-bot2-reference/docs/PROGRAM_REGISTRY_CONTROL.md index 5afb9ab..2509b4f 100644 --- a/migration/khadhroony-bot2-reference/docs/PROGRAM_REGISTRY_CONTROL.md +++ b/migration/khadhroony-bot2-reference/docs/PROGRAM_REGISTRY_CONTROL.md @@ -97,7 +97,7 @@ Ces identifiants sont détaillés dans `docs/CORE_PROGRAM_IDS.md`. Ils sont couv | `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` | | `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` | | `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` | -| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token_2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | +| `core_spl_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` | | `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token_2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` | | `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` | diff --git a/migration/khadhroony-bot2-reference/docs/RUST_WORKSPACE_RULE_AUDIT.md b/migration/khadhroony-bot2-reference/docs/RUST_WORKSPACE_RULE_AUDIT.md index 83206a2..8be870f 100644 --- a/migration/khadhroony-bot2-reference/docs/RUST_WORKSPACE_RULE_AUDIT.md +++ b/migration/khadhroony-bot2-reference/docs/RUST_WORKSPACE_RULE_AUDIT.md @@ -229,7 +229,7 @@ La mise en conformité est découpée avant toute nouvelle prérelease : 1. `pre.035-delta-fix-002` : séparation des règles et audit automatisé reproductible ; 2. correctifs suivants : points d'entrée de crates, réexports `pub`/`pub(crate)`, rustdocs et chemins `crate::...` ; 3. correctifs suivants : imports de traits et suppression des imports ordinaires/groupés ; -4. correctifs suivants : `TRACING_TARGET`, dépendances `tracing`, macros et matrice de routes ; +4. correctifs suivants : `DC_METADATA_MTM_TRACING_TARGET`, dépendances `tracing`, macros et matrice de routes ; 5. correctifs suivants : helpers dupliqués et mutualisation inter-crates ; 6. fermeture : `cargo fmt --all`, audit strict, tests workspace et Clippy global. diff --git a/migration/khadhroony-bot2-reference/docs/SOLANA_INTERFACE_DEPENDENCIES.md b/migration/khadhroony-bot2-reference/docs/SOLANA_INTERFACE_DEPENDENCIES.md index 4b1cd93..ace1f0a 100644 --- a/migration/khadhroony-bot2-reference/docs/SOLANA_INTERFACE_DEPENDENCIES.md +++ b/migration/khadhroony-bot2-reference/docs/SOLANA_INTERFACE_DEPENDENCIES.md @@ -62,7 +62,7 @@ Le message à signer provient de `solana_transaction::Transaction::message_data( ## Identifiants natifs, Vote et loaders dans l’exécuteur -`solana-sdk-ids` est conservé intentionnellement comme registre officiel modulaire des adresses natives et sysvars. Les chemins `solana_sdk_ids::sysvar::{clock,rent,slot_hashes,instructions}` ne constituent pas un retour au SDK monolithique : ils fournissent uniquement des `Pubkey` canoniques. `solana-instructions-sysvar` ne doit être ajouté que lorsqu’une crate appelle réellement ses fonctions d’introspection d’instructions, pas pour remplacer un simple ID officiel. +`solana-sdk-ids` est conservé intentionnellement comme registre officiel modulaire des adresses natives et sysvars. Les chemins `solana_sdk_ids::sysvar::{clock,rent,slot_hashes,instructions}` ne constituent pas un retour au SDK monolithique : ils fournissent uniquement des `MdPubkey` canoniques. `solana-instructions-sysvar` ne doit être ajouté que lorsqu’une crate appelle réellement ses fonctions d’introspection d’instructions, pas pour remplacer un simple ID officiel. `kb_executor_solana_core` consomme `solana-vote-interface ^6.0` avec `serde` et `wincode` pour construire les vingt variantes wire Vote actuelles. Il utilise `solana-instruction` pour `Instruction`/`AccountMeta`, `solana-pubkey::Pubkey` pour les adresses publiques, `solana-hash::Hash` pour les hashes et `solana-sdk-ids` pour Rent, Clock et SlotHashes. Les quatre créations composées utilisent `solana-system-interface`; aucune dépendance `solana-sdk` ni feature `bincode` n’est ajoutée à la crate. @@ -268,5 +268,5 @@ Le catalogue workspace déclare `mpl-token-metadata ^5.1` avec la seule feature Le dépôt officiel `metaplex-foundation/mpl-token-metadata` confirme le Program ID `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`. L’IDL officiel audité porte la version `1.14.0` et le blob `5df4a24f62c2743125be096cc174680790c92c18`; l’inventaire Rust généré des instructions porte le blob `3c42eec629f82e44ba690a7c4bd2177cc78f1d49`. -`kb_decoder_metadata_metaplex_token_metadata` implémente désormais `InstructionDecoder` pour `CreateMetadataAccountV3` et `UpdateMetadataAccountV2`. Les arguments sont lus avec les types Borsh officiels et projetés avec la feature `serde`; les payloads, chaînes, créateurs, frais, comptes et suffixes sont bornés. L’enregistrement dans le registre runtime reste différé jusqu’à validation de ce premier groupe. Les metadata Token-2022 incorporées, Metaplex Core, Bubblegum et le JSON externe restent des provenances ou composants distincts. +`kb_decoder_metadata_metaplex_token_metadata` implémente désormais `DcApiInstructionDecoder` pour `CreateMetadataAccountV3` et `UpdateMetadataAccountV2`. Les arguments sont lus avec les types Borsh officiels et projetés avec la feature `serde`; les payloads, chaînes, créateurs, frais, comptes et suffixes sont bornés. L’enregistrement dans le registre runtime reste différé jusqu’à validation de ce premier groupe. Les metadata Token-2022 incorporées, Metaplex Core, Bubblegum et le JSON externe restent des provenances ou composants distincts. diff --git a/migration/khadhroony-bot2-reference/kb_decoder_api/README.md b/migration/khadhroony-bot2-reference/kb_decoder_api/README.md index 072f5dd..3cec350 100644 --- a/migration/khadhroony-bot2-reference/kb_decoder_api/README.md +++ b/migration/khadhroony-bot2-reference/kb_decoder_api/README.md @@ -18,8 +18,8 @@ Ce module fait partie du découpage strict de Khadhroony Bot2. Il doit conserver ## Contrats `0.4.0` et contexte core `2` -Le trait `InstructionDecoder` reçoit exclusivement `CoreInstructionReplayInput`. Il expose une identité et une version stables, les surfaces supportées, la couverture déclarée, la reconnaissance déterministe et un résultat explicite `decoded`, `ignored`, `unsupported` ou `failed`. Les observations produites conservent la preuve, la confiance, le statut on-chain et le caractère commité ou annulé. +Le trait `DcApiInstructionDecoder` reçoit exclusivement `MdCoreInstructionReplayInput`. Il expose une identité et une version stables, les surfaces supportées, la couverture déclarée, la reconnaissance déterministe et un résultat explicite `decoded`, `ignored`, `unsupported` ou `failed`. Les observations produites conservent la preuve, la confiance, le statut on-chain et le caractère commité ou annulé. -Depuis `0.4.1-pre.014`, le même contrat inclut les payloads ordonnés des instructions outer. `contextual_input_hash` sérialise l’ensemble du contexte, trie récursivement les clés d’objets et conserve l’ordre des tableaux. Un changement de payload outer modifie donc le hash, tandis qu’un contexte identique produit un hash stable. +Depuis `0.4.1-pre.014`, le même contrat inclut les payloads ordonnés des instructions outer. `decoder_api_decoder_api_contextual_input_hash` sérialise l’ensemble du contexte, trie récursivement les clés d’objets et conserve l’ordre des tableaux. Un changement de payload outer modifie donc le hash, tandis qu’un contexte identique produit un hash stable. Le crate reste indépendant de PostgreSQL, Tauri et des fournisseurs RPC. diff --git a/migration/khadhroony-bot2-reference/kb_decoder_metadata_metaplex_token_metadata/README.md b/migration/khadhroony-bot2-reference/kb_decoder_metadata_metaplex_token_metadata/README.md index cb96b4c..26264f9 100644 --- a/migration/khadhroony-bot2-reference/kb_decoder_metadata_metaplex_token_metadata/README.md +++ b/migration/khadhroony-bot2-reference/kb_decoder_metadata_metaplex_token_metadata/README.md @@ -8,7 +8,7 @@ Décodeur contextualisé dédié au programme Metaplex Token Metadata. La crate suit la frontière commune des décodeurs opérationnels du workspace : - `constants.rs` contient la surface, les discriminateurs, les bornes et la cible de tracing ; -- `decoder.rs` implémente `ProtocolDecoder` et `InstructionDecoder` ; +- `decoder.rs` implémente `DcApiProtocolDecoder` et `DcApiInstructionDecoder` ; - `instruction.rs` contient le décodage Borsh borné, la résolution des comptes et les observations ; - `lib.rs` réexporte le décodeur d’instructions et les types publics du parseur de comptes ; - le Program ID provient exclusivement de `kb_program_ids`. @@ -111,11 +111,11 @@ Le discriminant `50` décode `UpdateArgs` et toutes ses variantes publiées : `V ## `0.4.7-pre.025` — premier compte on-chain -La crate expose désormais `decode_metadata_account` pour le layout officiel `Metadata`. Le parseur refuse un owner étranger avant désérialisation, exige `Key::MetadataV1`, borne les données et les champs textuels, limite les creators, valide le PDA canonique `[metadata, program_id, mint]` et conserve le bump. Cette tranche ne couvre pas encore MasterEdition, Edition, EditionMarker, TokenRecord ni les records de délégation. +La crate expose désormais `decoder_metadata_metaplex_token_metadata_decode_metadata_account` pour le layout officiel `Metadata`. Le parseur refuse un owner étranger avant désérialisation, exige `Key::MetadataV1`, borne les données et les champs textuels, limite les creators, valide le PDA canonique `[metadata, program_id, mint]` et conserve le bump. Cette tranche ne couvre pas encore MasterEdition, Edition, EditionMarker, TokenRecord ni les records de délégation. ## `0.4.7-pre.026` — comptes edition et master edition -La crate expose `decode_edition_account` pour `DeprecatedMasterEditionV1`, `MasterEditionV2` et `EditionV1`. Le décodeur vérifie l’owner avant parsing, exige le PDA commun `[metadata, program_id, mint, edition]`, conserve le bump et projette supply/max supply, printing mints historiques, parent et numéro d’édition. `MasterEditionV1` reste historique et decode-only ; `MasterEditionV2` et `EditionV1` alimenteront les futures projections stateful. +La crate expose `decoder_metadata_metaplex_token_metadata_decode_edition_account` pour `DeprecatedMasterEditionV1`, `MasterEditionV2` et `EditionV1`. Le décodeur vérifie l’owner avant parsing, exige le PDA commun `[metadata, program_id, mint, edition]`, conserve le bump et projette supply/max supply, printing mints historiques, parent et numéro d’édition. `MasterEditionV1` reste historique et decode-only ; `MasterEditionV2` et `EditionV1` alimenteront les futures projections stateful. ## `0.4.7-pre.027` — Edition Marker V1/V2 diff --git a/migration/khadhroony-bot2-reference/kb_decoder_solana_core/README.md b/migration/khadhroony-bot2-reference/kb_decoder_solana_core/README.md index 43a9620..2c5f3cc 100644 --- a/migration/khadhroony-bot2-reference/kb_decoder_solana_core/README.md +++ b/migration/khadhroony-bot2-reference/kb_decoder_solana_core/README.md @@ -7,7 +7,7 @@ Ce crate décode les programmes Solana natifs/runtime, les programmes historique ## Rôle dans l'écosystème -`SolanaCoreDecoder` implémente le contrat commun `InstructionDecoder` et consomme uniquement les inputs contextualisés produits par l’extraction core. Il ne dépend ni de PostgreSQL, ni de Tauri, ni d’un fournisseur RPC. +`DcSolanaCoreDecoder` implémente le contrat commun `DcApiInstructionDecoder` et consomme uniquement les inputs contextualisés produits par l’extraction core. Il ne dépend ni de PostgreSQL, ni de Tauri, ni d’un fournisseur RPC. Le processor conserve l’identité stable `solana_native_classifier` introduite en `0.4.0`. Cette continuité permet au ledger processor/version/hash de remplacer les anciens résultats `unsupported` lors d’un force replay. La version du processor reste `0.4.1` pendant les deltas préparatoires. @@ -71,7 +71,7 @@ Chaque observation décodée contient notamment : - `eventVersion` ; - program ID, surface et entry code ; -- signature, slot et chemin outer/inner via `DecodedProtocolEvent` ; +- signature, slot et chemin outer/inner via `MdDecodedProtocolEvent` ; - paramètres numériques sans perte ; - comptes résolus avec rôle, index, clé et privilèges attendus/observés ; - `transactionSucceeded` ; diff --git a/migration/khadhroony-bot2-reference/kb_decoder_spl_memo/README.md b/migration/khadhroony-bot2-reference/kb_decoder_spl_memo/README.md index 1ec6305..75567c4 100644 --- a/migration/khadhroony-bot2-reference/kb_decoder_spl_memo/README.md +++ b/migration/khadhroony-bot2-reference/kb_decoder_spl_memo/README.md @@ -11,7 +11,7 @@ Ce crate décode les programmes SPL Memo v1, v3 et v4 depuis l’instruction cor - v3 : `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` ; - v4 : `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH`. -`SplMemoDecoder` implémente le contrat contextualisé `InstructionDecoder`. La reconnaissance est exacte pour ces trois IDs et incompatible avec tout autre programme. L’adaptateur historique `ProtocolDecoder` déclare `Yes` pour ces IDs, mais ne fabrique pas d’événement sans instruction contextualisée. +`DcSplMemoDecoder` implémente le contrat contextualisé `DcApiInstructionDecoder`. La reconnaissance est exacte pour ces trois IDs et incompatible avec tout autre programme. L’adaptateur historique `DcApiProtocolDecoder` déclare `Yes` pour ces IDs, mais ne fabrique pas d’événement sans instruction contextualisée. ## Contrat décodé diff --git a/migration/khadhroony-bot2-reference/kb_decoder_spl_token/README.md b/migration/khadhroony-bot2-reference/kb_decoder_spl_token/README.md index 4b52d58..1cf852f 100644 --- a/migration/khadhroony-bot2-reference/kb_decoder_spl_token/README.md +++ b/migration/khadhroony-bot2-reference/kb_decoder_spl_token/README.md @@ -24,10 +24,10 @@ est `docs/SPL_TOKEN_MATRIX.json`. ## Contrat de décodage -`SplTokenDecoder` implémente les deux contrats communs : +`DcSplTokenDecoder` implémente les deux contrats communs : -- `ProtocolDecoder` annonce `Yes` uniquement pour le Program ID Token classique exact ; -- `InstructionDecoder` fournit une surface, 28 déclarations de couverture, une reconnaissance par +- `DcApiProtocolDecoder` annonce `Yes` uniquement pour le Program ID Token classique exact ; +- `DcApiInstructionDecoder` fournit une surface, 28 déclarations de couverture, une reconnaissance par tag et un résultat contextualisé pour le replay commun. Chaque observation conserve le tag, le wire borné et son SHA-256, le chemin outer/inner, les @@ -58,7 +58,7 @@ comptes insuffisants ou batch imbriqué échoue avec un diagnostic borné. ## Limites actuelles -- Le contrat `CoreInstructionReplayInput` ne transporte pas encore les return data canoniques ; les +- Le contrat `MdCoreInstructionReplayInput` ne transporte pas encore les return data canoniques ; les trois conversions concernées restent décodées comme intentions, avec validation de return data explicitement indisponible. - Le corpus Mainnet prouve les opérations réellement observées, pas l'exhaustivité des 28 tags sur diff --git a/migration/khadhroony-bot2-reference/kb_execution_api/README.md b/migration/khadhroony-bot2-reference/kb_execution_api/README.md index 577f13a..5a09b0a 100644 --- a/migration/khadhroony-bot2-reference/kb_execution_api/README.md +++ b/migration/khadhroony-bot2-reference/kb_execution_api/README.md @@ -11,56 +11,56 @@ Cette crate définit les contrats communs de la couche d’exécution. Elle ne d | Export | Usage | |-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------| -| `ExecutionCapability` | Réponse exacte `Supported { operation_code }` ou `Unsupported { reason_code, reason }` pour un couple programme/opération. | +| `ExApiExecutionCapability` | Réponse exacte `Supported { operation_code }` ou `Unsupported { reason_code, reason }` pour un couple programme/opération. | | `ExecutionCapability::supported(...)` | Construit une capacité supportée avec un code stable. | | `ExecutionCapability::unsupported(...)` | Construit un refus documenté avec code et message. | | `ExecutionCapability::is_supported()` | Teste la capacité sans perdre le diagnostic du variant complet. | -| `TypedInstructionExecutor` | Contrat actuel : expose `capability(...)` et `build_prepared_plan(...)` sans I/O, signature ou envoi. | -| `InstructionExecutor` | Pont historique fondé sur `ExecutionRequest`/`ExecutionPlan`; il reste disponible pour les crates réservées. | -| `ExecutionSupport` | Résultat historique `No`, `Maybe` ou `Yes`; les exécuteurs opérationnels doivent éviter `Maybe`. | +| `ExApiTypedInstructionExecutor` | Contrat actuel : expose `capability(...)` et `build_prepared_plan(...)` sans I/O, signature ou envoi. | +| `ExApiInstructionExecutor` | Pont historique fondé sur `ExApiExecutionRequest`/`ExApiExecutionPlan`; il reste disponible pour les crates réservées. | +| `ExApiExecutionSupport` | Résultat historique `No`, `Maybe` ou `Yes`; les exécuteurs opérationnels doivent éviter `Maybe`. | ### Politiques -| Export | Usage | -|---------------------------------|-----------------------------------------------------------------------------------------------------------| -| `ExecutionPolicy` | Agrège cluster, simulation, blockhash/nonce, plafonds, signataires autorisés, dry-run et post-validation. | -| `ExecutionCluster` | Cluster attendu : Localnet, Devnet, Testnet ou Mainnet. | -| `ExecutionClusterPolicy` | Autorisation du cluster et double confirmation Mainnet. | -| `ExecutionSimulationPolicy` | Indique si la simulation est obligatoire. | -| `ExecutionBlockhashKind` | Sélectionne un recent blockhash ou un durable nonce. | -| `ExecutionBlockhashPolicy` | Porte l’âge maximal du blockhash ou le compte et l’autorité nonce. | -| `ExecutionCostLimit` | Plafonds de dépense, frais totaux et prix par compute unit. | -| `PostExecutionValidationPolicy` | Étapes exigées après confirmation : canonical insert, core extraction, decode replay et matérialisation. | +| Export | Usage | +|--------------------------------------|-----------------------------------------------------------------------------------------------------------| +| `ExApiExecutionPolicy` | Agrège cluster, simulation, blockhash/nonce, plafonds, signataires autorisés, dry-run et post-validation. | +| `ExApiExecutionCluster` | Cluster attendu : Localnet, Devnet, Testnet ou Mainnet. | +| `ExApiExecutionClusterPolicy` | Autorisation du cluster et double confirmation Mainnet. | +| `ExApiExecutionSimulationPolicy` | Indique si la simulation est obligatoire. | +| `ExApiExecutionBlockhashKind` | Sélectionne un recent blockhash ou un durable nonce. | +| `ExApiExecutionBlockhashPolicy` | Porte l’âge maximal du blockhash ou le compte et l’autorité nonce. | +| `ExApiExecutionCostLimit` | Plafonds de dépense, frais totaux et prix par compute unit. | +| `ExApiPostExecutionValidationPolicy` | Étapes exigées après confirmation : canonical insert, core extraction, decode replay et matérialisation. | Tous les types de politique implémentent des valeurs par défaut conservatrices : Devnet, simulation obligatoire, recent blockhash borné, dry-run actif et Mainnet désactivé. ### Plan préparé -| Export | Usage | -|-------------------------|-------------------------------------------------------------------------------------| -| `PreparedExecutionPlan` | Contrat immutable transmis de l’exécuteur à la sécurité puis à l’assembleur Solana. | -| `PlannedInstruction` | Program ID, code d’opération, comptes ordonnés et payload exact. | -| `PlannedAccount` | Public key et flags signer/writable d’un compte d’instruction. | -| `RequiredSigner` | Public key et rôle stable d’un signataire requis. | +| Export | Usage | +|------------------------------|-------------------------------------------------------------------------------------| +| `ExApiPreparedExecutionPlan` | Contrat immutable transmis de l’exécuteur à la sécurité puis à l’assembleur Solana. | +| `ExApiPlannedInstruction` | Program ID, code d’opération, comptes ordonnés et payload exact. | +| `ExApiPlannedAccount` | Public key et flags signer/writable d’un compte d’instruction. | +| `ExApiRequiredSigner` | Public key et rôle stable d’un signataire requis. | Un plan contient également l’exécuteur/version, l’identifiant d’intent, le fee payer, la politique, les lamports dépensés ou verrouillés et le prix Compute Budget demandé. ### Résultats d’orchestration -| Export | Usage | -|-------------------------------|-------------------------------------------------------------------------------------------------------------------| -| `ExecutionSimulationResult` | Preuve provider-neutral d’une simulation, avec contexte cluster/blockhash, frais, unités, logs et erreur runtime. | -| `ExecutionSendResult` | Signature acceptée par le RPC et slot de soumission éventuel. | -| `ExecutionConfirmationStatus` | État final ou intermédiaire de confirmation. | -| `ExecutionConfirmationResult` | Résultat borné des polls de confirmation. | -| `PostExecutionDiagnostic` | Résumé des étapes canonical/core/decode/materialization après exécution. | +| Export | Usage | +|------------------------------------|-------------------------------------------------------------------------------------------------------------------| +| `ExApiExecutionSimulationResult` | Preuve provider-neutral d’une simulation, avec contexte cluster/blockhash, frais, unités, logs et erreur runtime. | +| `ExApiExecutionSendResult` | Signature acceptée par le RPC et slot de soumission éventuel. | +| `ExApiExecutionConfirmationStatus` | État final ou intermédiaire de confirmation. | +| `ExApiExecutionConfirmationResult` | Résultat borné des polls de confirmation. | +| `ExApiPostExecutionDiagnostic` | Résumé des étapes canonical/core/decode/materialization après exécution. | ### Compatibilité et helpers JSON | Export | Usage | |--------------------------------------|------------------------------------------------------------------------| -| `ExecutionRequest` | Requête historique `program_id + operation_code + payload_json`. | -| `ExecutionPlan` | Plan historique sérialisé, sans garantie d’être directement envoyable. | +| `ExApiExecutionRequest` | Requête historique `program_id + operation_code + payload_json`. | +| `ExApiExecutionPlan` | Plan historique sérialisé, sans garantie d’être directement envoyable. | | `serialize_payload_json(...)` | Sérialise un `serde_json::Value` compact avec `kb_core::Error`. | | `serialize_payload_json_pretty(...)` | Sérialise le même payload en forme lisible. | diff --git a/migration/khadhroony-bot2-reference/kb_execution_safety/README.md b/migration/khadhroony-bot2-reference/kb_execution_safety/README.md index 4f37c19..8e8f924 100644 --- a/migration/khadhroony-bot2-reference/kb_execution_safety/README.md +++ b/migration/khadhroony-bot2-reference/kb_execution_safety/README.md @@ -16,11 +16,11 @@ Cette crate applique des contrôles stateless communs aux plans préparés avant ### `ExecutionSafetyChecker::evaluate_plan(plan)` -Évalue l’ancien `ExecutionPlan`. Ce contrat historique ne contient pas assez d’informations pour autoriser directement une exécution ; la décision reste donc conservatrice et exige une confirmation. +Évalue l’ancien `ExApiExecutionPlan`. Ce contrat historique ne contient pas assez d’informations pour autoriser directement une exécution ; la décision reste donc conservatrice et exige une confirmation. ### `ExecutionSafetyChecker::evaluate_prepared_plan(plan)` -Décide si un `PreparedExecutionPlan` peut atteindre la simulation RPC. La fonction vérifie notamment : +Décide si un `ExApiPreparedExecutionPlan` peut atteindre la simulation RPC. La fonction vérifie notamment : - présence d’instructions et de signataires ; - simulation obligatoire ; diff --git a/migration/khadhroony-bot2-reference/kb_execution_solana/README.md b/migration/khadhroony-bot2-reference/kb_execution_solana/README.md index 1ab6f35..ef4b75c 100644 --- a/migration/khadhroony-bot2-reference/kb_execution_solana/README.md +++ b/migration/khadhroony-bot2-reference/kb_execution_solana/README.md @@ -3,7 +3,7 @@ # kb_execution_solana -`kb_execution_solana` transforme un `PreparedExecutionPlan` commun en message et transaction Solana, puis résout les signataires via l’interface Solana `Signer` et signe uniquement après une simulation autorisée par `kb_execution_safety`. +`kb_execution_solana` transforme un `ExApiPreparedExecutionPlan` commun en message et transaction Solana, puis résout les signataires via l’interface Solana `Signer` et signe uniquement après une simulation autorisée par `kb_execution_safety`. La crate est indépendante des exécuteurs concrets et des transports RPC. Elle assemble aussi bien les plans à recent blockhash que les transactions consommant réellement un durable nonce. diff --git a/migration/khadhroony-bot2-reference/kb_executor_solana_core/README.md b/migration/khadhroony-bot2-reference/kb_executor_solana_core/README.md index 20dc88b..1c553fe 100644 --- a/migration/khadhroony-bot2-reference/kb_executor_solana_core/README.md +++ b/migration/khadhroony-bot2-reference/kb_executor_solana_core/README.md @@ -18,10 +18,10 @@ Elle ne charge aucun wallet, ne signe rien, n’appelle aucun RPC et n’envoie | Fonction | Paramètres | Résultat | Rôle | |-------------------------------------------------|--------------------------------------------------|------------------------------------------|------------------------------------------------------------------------------------------------------------------| -| `TypedInstructionExecutor::capability` | `program_id: &ProgramId`, `operation_code: &str` | `ExecutionCapability` | Indique exactement si le couple programme/opération possède un builder. | +| `TypedInstructionExecutor::capability` | `program_id: &ProgramId`, `operation_code: &str` | `ExApiExecutionCapability` | Indique exactement si le couple programme/opération possède un builder. | | `TypedInstructionExecutor::build_prepared_plan` | `intent: &SolanaCoreExecutionIntent` | `kb_core::Result` | Valide l’intent, construit l’instruction officielle et déclare comptes, signataires, coût et politique. | | `InstructionExecutor::program_ids` | aucun | `&'static [&'static str]` | Retourne les dix-huit program IDs natifs classifiés par la crate. | -| `InstructionExecutor::supports_request` | `request: &ExecutionRequest` | `ExecutionSupport` | Pont historique exact `Yes/No`, sans état `Maybe`. | +| `InstructionExecutor::supports_request` | `request: &ExecutionRequest` | `ExApiExecutionSupport` | Pont historique exact `Yes/No`, sans état `Maybe`. | | `InstructionExecutor::build_plan` | `request: &ExecutionRequest` | `kb_core::Result` | Désérialise un `SolanaCoreExecutionIntent`, construit le plan typé puis le sérialise dans le contrat historique. | ### Types et constantes réexportés @@ -52,7 +52,7 @@ Elle ne charge aucun wallet, ne signe rien, n’appelle aucun RPC et n’envoie | `LOADER_V3_*_OPERATION` | Codes stables des onze plans Loader v3. | | `LOADER_V4_*_OPERATION` | Codes stables des neuf plans Loader v4. | -Les modules internes ne sont pas publics. Les appelants utilisent les réexports de `lib.rs` et les traits de `kb_execution_api`. Le module privé `validation` centralise le parsing des `Pubkey`, les IDs natifs, les contrôles de longueur, de montants positifs, de comptes distincts, de dérivation seedée et la construction d’erreurs partagées ; les modules de programme conservent uniquement leurs règles et libellés métier. +Les modules internes ne sont pas publics. Les appelants utilisent les réexports de `lib.rs` et les traits de `kb_execution_api`. Le module privé `validation` centralise le parsing des `MdPubkey`, les IDs natifs, les contrôles de longueur, de montants positifs, de comptes distincts, de dérivation seedée et la construction d’erreurs partagées ; les modules de programme conservent uniquement leurs règles et libellés métier. ## Contrat d’intent et résultat @@ -69,10 +69,10 @@ SolanaCoreExecutionIntent { - `intent_id` : identifiant stable fourni par l’appelant pour les logs et la corrélation ; - `fee_payer` : compte qui paiera les frais de transaction ; -- `policy` : `ExecutionPolicy` évaluée séparément par `kb_execution_safety` ; +- `policy` : `ExApiExecutionPolicy` évaluée séparément par `kb_execution_safety` ; - `operation` : variante typée de `SolanaCoreOperation`. -Le résultat `PreparedExecutionPlan` contient : +Le résultat `ExApiPreparedExecutionPlan` contient : - l’exécuteur et sa version ; - le code d’opération ; @@ -114,11 +114,11 @@ Cent neuf opérations disposent d’un builder : dix-sept System, quatre Compute SolanaCoreOperation::SystemTransfer { from, to, lamports } ``` -| Paramètre | Type | Description | -|------------|----------|-----------------------------------------| -| `from` | `Pubkey` | Compte source writable et signataire. | -| `to` | `Pubkey` | Compte destinataire writable. | -| `lamports` | `u64` | Montant transféré, strictement positif. | +| Paramètre | Type | Description | +|------------|------------|-----------------------------------------| +| `from` | `MdPubkey` | Compte source writable et signataire. | +| `to` | `MdPubkey` | Compte destinataire writable. | +| `lamports` | `u64` | Montant transféré, strictement positif. | **Résultat et effet :** une instruction System `Transfer`. Le plan exige `from`, ajoute le fee payer si nécessaire et reporte `lamports` dans `requested_spend_lamports`. @@ -146,14 +146,14 @@ SolanaCoreOperation::SystemTransferWithSeed { } ``` -| Paramètre | Type | Description | -|--------------|----------|------------------------------------------------------------| -| `from` | `Pubkey` | Compte source dérivé, writable mais non signataire direct. | -| `from_base` | `Pubkey` | Base de dérivation et signataire requis. | -| `from_seed` | `String` | Seed utilisé pour dériver `from`. | -| `from_owner` | `Pubkey` | Owner utilisé dans la dérivation de `from`. | -| `to` | `Pubkey` | Destinataire writable. | -| `lamports` | `u64` | Montant strictement positif. | +| Paramètre | Type | Description | +|--------------|------------|------------------------------------------------------------| +| `from` | `MdPubkey` | Compte source dérivé, writable mais non signataire direct. | +| `from_base` | `MdPubkey` | Base de dérivation et signataire requis. | +| `from_seed` | `String` | Seed utilisé pour dériver `from`. | +| `from_owner` | `MdPubkey` | Owner utilisé dans la dérivation de `from`. | +| `to` | `MdPubkey` | Destinataire writable. | +| `lamports` | `u64` | Montant strictement positif. | **Résultat et effet :** une instruction System `TransferWithSeed`. Le builder recalcule `Pubkey::create_with_seed(from_base, from_seed, from_owner)` et refuse l’intent si l’adresse obtenue diffère de `from`. @@ -169,13 +169,13 @@ SolanaCoreOperation::SystemCreateAccount { } ``` -| Paramètre | Type | Description | -|---------------|----------|---------------------------------------------------------------------------------| -| `from` | `Pubkey` | Compte de financement writable et signataire. | -| `new_account` | `Pubkey` | Nouveau compte writable et signataire. | -| `lamports` | `u64` | Financement initial, strictement positif. | -| `space` | `u64` | Taille de données allouée ; zéro est valide pour un compte System sans données. | -| `owner` | `Pubkey` | Programme propriétaire après création. | +| Paramètre | Type | Description | +|---------------|------------|---------------------------------------------------------------------------------| +| `from` | `MdPubkey` | Compte de financement writable et signataire. | +| `new_account` | `MdPubkey` | Nouveau compte writable et signataire. | +| `lamports` | `u64` | Financement initial, strictement positif. | +| `space` | `u64` | Taille de données allouée ; zéro est valide pour un compte System sans données. | +| `owner` | `MdPubkey` | Programme propriétaire après création. | **Résultat et effet :** une instruction officielle `CreateAccount` qui finance, alloue et assigne le compte. Le calcul du minimum rent-exempt appartient à la couche RPC/orchestration. @@ -193,15 +193,15 @@ SolanaCoreOperation::SystemCreateAccountWithSeed { } ``` -| Paramètre | Type | Description | -|---------------|----------|------------------------------------------------------| -| `from` | `Pubkey` | Compte de financement writable et signataire. | -| `new_account` | `Pubkey` | Adresse créée à partir de `base`, `seed` et `owner`. | -| `base` | `Pubkey` | Base signataire ; elle peut être identique à `from`. | -| `seed` | `String` | Seed borné par l’interface Solana. | -| `lamports` | `u64` | Financement initial strictement positif. | -| `space` | `u64` | Taille allouée, zéro compris. | -| `owner` | `Pubkey` | Owner du compte et composant de sa dérivation. | +| Paramètre | Type | Description | +|---------------|------------|------------------------------------------------------| +| `from` | `MdPubkey` | Compte de financement writable et signataire. | +| `new_account` | `MdPubkey` | Adresse créée à partir de `base`, `seed` et `owner`. | +| `base` | `MdPubkey` | Base signataire ; elle peut être identique à `from`. | +| `seed` | `String` | Seed borné par l’interface Solana. | +| `lamports` | `u64` | Financement initial strictement positif. | +| `space` | `u64` | Taille allouée, zéro compris. | +| `owner` | `MdPubkey` | Owner du compte et composant de sa dérivation. | **Résultat et effet :** une instruction `CreateAccountWithSeed`. Le builder recalcule l’adresse dérivée avant de construire le plan et déduplique `from`/`base` lorsqu’ils désignent le même signataire. @@ -219,11 +219,11 @@ SolanaCoreOperation::SystemCreateAccountAllowPrefund { | Paramètre | Type | Description | |---------------|------------------|------------------------------------------------------------------| -| `new_account` | `Pubkey` | Compte préfinancé à créer, writable et toujours signataire. | +| `new_account` | `MdPubkey` | Compte préfinancé à créer, writable et toujours signataire. | | `payer` | `Option` | Payer writable/signataire pour des lamports additionnels. | | `lamports` | `u64` | Montant additionnel ; doit être zéro lorsque `payer` est absent. | | `space` | `u64` | Taille de données à allouer, zéro compris. | -| `owner` | `Pubkey` | Programme propriétaire après création. | +| `owner` | `MdPubkey` | Programme propriétaire après création. | **Résultat et effet :** une instruction `CreateAccountAllowPrefund`, qui n’impose pas un solde initial nul. Cette opération peut verrouiller tout le solde existant dans le compte assigné ; elle doit être protégée par une politique appelante stricte et peut dépendre de l’activation runtime correspondante sur le cluster ciblé. @@ -233,10 +233,10 @@ SolanaCoreOperation::SystemCreateAccountAllowPrefund { SolanaCoreOperation::SystemAllocate { account, space } ``` -| Paramètre | Type | Description | -|-----------|----------|---------------------------------------| -| `account` | `Pubkey` | Compte System writable et signataire. | -| `space` | `u64` | Nouvelle taille strictement positive. | +| Paramètre | Type | Description | +|-----------|------------|---------------------------------------| +| `account` | `MdPubkey` | Compte System writable et signataire. | +| `space` | `u64` | Nouvelle taille strictement positive. | **Résultat et effet :** une instruction `Allocate`. Elle ne finance pas le compte et ne change pas son propriétaire. @@ -252,13 +252,13 @@ SolanaCoreOperation::SystemAllocateWithSeed { } ``` -| Paramètre | Type | Description | -|-----------|----------|--------------------------------------------------------| -| `account` | `Pubkey` | Compte dérivé writable. | -| `base` | `Pubkey` | Base de dérivation et signataire requis. | -| `seed` | `String` | Seed de dérivation. | -| `space` | `u64` | Taille strictement positive. | -| `owner` | `Pubkey` | Owner utilisé dans la dérivation et assigné au compte. | +| Paramètre | Type | Description | +|-----------|------------|--------------------------------------------------------| +| `account` | `MdPubkey` | Compte dérivé writable. | +| `base` | `MdPubkey` | Base de dérivation et signataire requis. | +| `seed` | `String` | Seed de dérivation. | +| `space` | `u64` | Taille strictement positive. | +| `owner` | `MdPubkey` | Owner utilisé dans la dérivation et assigné au compte. | **Résultat et effet :** une instruction `AllocateWithSeed`. L’adresse `account` est recalculée et validée avant construction. @@ -268,10 +268,10 @@ SolanaCoreOperation::SystemAllocateWithSeed { SolanaCoreOperation::SystemAssign { account, owner } ``` -| Paramètre | Type | Description | -|-----------|----------|---------------------------------------| -| `account` | `Pubkey` | Compte System writable et signataire. | -| `owner` | `Pubkey` | Nouveau programme propriétaire. | +| Paramètre | Type | Description | +|-----------|------------|---------------------------------------| +| `account` | `MdPubkey` | Compte System writable et signataire. | +| `owner` | `MdPubkey` | Nouveau programme propriétaire. | **Résultat et effet :** une instruction `Assign`. Elle ne transfère aucun lamport et n’alloue aucune donnée. @@ -286,12 +286,12 @@ SolanaCoreOperation::SystemAssignWithSeed { } ``` -| Paramètre | Type | Description | -|-----------|----------|------------------------------------------------------| -| `account` | `Pubkey` | Compte dérivé writable. | -| `base` | `Pubkey` | Base de dérivation et signataire requis. | -| `seed` | `String` | Seed de dérivation. | -| `owner` | `Pubkey` | Nouvel owner et composant de la dérivation attendue. | +| Paramètre | Type | Description | +|-----------|------------|------------------------------------------------------| +| `account` | `MdPubkey` | Compte dérivé writable. | +| `base` | `MdPubkey` | Base de dérivation et signataire requis. | +| `seed` | `String` | Seed de dérivation. | +| `owner` | `MdPubkey` | Nouvel owner et composant de la dérivation attendue. | **Résultat et effet :** une instruction `AssignWithSeed`. Le builder refuse une adresse qui ne correspond pas exactement à `base + seed + owner`. diff --git a/migration/khadhroony-bot2-reference/kb_executor_spl_memo/README.md b/migration/khadhroony-bot2-reference/kb_executor_spl_memo/README.md index bf06ea5..b0de999 100644 --- a/migration/khadhroony-bot2-reference/kb_executor_spl_memo/README.md +++ b/migration/khadhroony-bot2-reference/kb_executor_spl_memo/README.md @@ -39,7 +39,7 @@ La construction de plan est `Supported` pour `AddMemo` uniquement sur l'ID v4 ex La disponibilité effective de v4 sur un cluster n’est pas supposée par le builder : elle est établie par la simulation RPC obligatoire. Une future génération expérimentale officiellement encodée pourra être ajoutée sans la limiter artificiellement à un cluster. Les générations historiques restent décodables dans `kb_decoder_spl_memo`, mais ne sont pas exécutables. La démo `0.4.3` reste limitée à Devnet. -Les signataires restent visibles dans `PreparedExecutionPlan` avant toute signature. Les clés privées ne font partie ni de l’intent ni du plan. +Les signataires restent visibles dans `ExApiPreparedExecutionPlan` avant toute signature. Les clés privées ne font partie ni de l’intent ni du plan. ## Validation Devnet et démos diff --git a/migration/khadhroony-bot2-reference/kb_executor_spl_token/README.md b/migration/khadhroony-bot2-reference/kb_executor_spl_token/README.md index 2585d05..fe639f4 100644 --- a/migration/khadhroony-bot2-reference/kb_executor_spl_token/README.md +++ b/migration/khadhroony-bot2-reference/kb_executor_spl_token/README.md @@ -29,7 +29,7 @@ obsolètes. Les variantes checked doivent être préférées lorsqu’un mint et `SplTokenExecutionIntent` contient : - un identifiant d’intent et un fee payer ; -- une `ExecutionPolicy` commune, simulation obligatoire et dry-run par défaut ; +- une `ExApiExecutionPolicy` commune, simulation obligatoire et dry-run par défaut ; - une instruction typée ou un `Batch` de sous-instructions non batch ; - les comptes métier explicites ; - une autorité simple ou un multisig avec signataires ordonnés ; @@ -71,7 +71,7 @@ instruction Token ; le préflight stateful de la tranche suivante les vérifiera Les montants token ne sont pas des frais réseau et ne sont pas reportés comme lamports dépensés. Un montant explicite `UnwrapLamports` est déclaré dans `requested_spend_lamports`; un unwrap total et `WithdrawExcessLamports` restent simulation-only tant qu’une lecture d’état n’a pas borné les -lamports déplaçables. Le plafond de frais reste séparé dans `ExecutionCostLimit`. +lamports déplaçables. Le plafond de frais reste séparé dans `ExApiExecutionCostLimit`. Toute construction impose une simulation, un plafond de frais positif, une insertion canonique, l’extraction core et le replay décodé. Les mutations exigent aussi la validation de matérialisation ; diff --git a/migration/khadhroony-bot2-reference/kb_materializer_admin/README.md b/migration/khadhroony-bot2-reference/kb_materializer_admin/README.md index 520e47f..95c5de9 100644 --- a/migration/khadhroony-bot2-reference/kb_materializer_admin/README.md +++ b/migration/khadhroony-bot2-reference/kb_materializer_admin/README.md @@ -22,4 +22,4 @@ Les instructions ATA ne modifient aucune autorité de mint, freeze, close ou mul ## État ElGamal Registry -`materialize_elgamal_registry_state_snapshot` projette l’état exact lu du compte registre (`owner`, clé ElGamal publique et wire). Cette projection ne prétend pas revalider la preuve cryptographique depuis les seuls octets du compte et ne déchiffre aucune valeur. +`materializer_admin_materialize_elgamal_registry_state_snapshot` projette l’état exact lu du compte registre (`owner`, clé ElGamal publique et wire). Cette projection ne prétend pas revalider la preuve cryptographique depuis les seuls octets du compte et ne déchiffre aucune valeur. diff --git a/migration/khadhroony-bot2-reference/kb_materializer_api/README.md b/migration/khadhroony-bot2-reference/kb_materializer_api/README.md index 5ef5776..dcd97b5 100644 --- a/migration/khadhroony-bot2-reference/kb_materializer_api/README.md +++ b/migration/khadhroony-bot2-reference/kb_materializer_api/README.md @@ -18,7 +18,7 @@ Ce module fait partie du découpage strict de Khadhroony Bot2. Il doit conserver ## Contrats `0.4.0` -Le trait `EventMaterializer` consomme des observations décodées stables et déclare les familles acceptées, l’applicabilité exacte par observation ainsi que la politique applicable aux transactions réussies ou échouées. Les sorties possèdent des clés idempotentes et un statut explicite `inserted`, `replaced`, `ignored`, `refused` ou `failed`. +Le trait `MtApiEventMaterializer` consomme des observations décodées stables et déclare les familles acceptées, l’applicabilité exacte par observation ainsi que la politique applicable aux transactions réussies ou échouées. Les sorties possèdent des clés idempotentes et un statut explicite `inserted`, `replaced`, `ignored`, `refused` ou `failed`. La garde commune refuse toute matérialisation de trade, liquidité ou lifecycle supposée réussie depuis une observation échouée ou non commitée. diff --git a/migration/khadhroony-bot2-reference/kb_materializer_metadata/README.md b/migration/khadhroony-bot2-reference/kb_materializer_metadata/README.md index 74be6e5..292d0db 100644 --- a/migration/khadhroony-bot2-reference/kb_materializer_metadata/README.md +++ b/migration/khadhroony-bot2-reference/kb_materializer_metadata/README.md @@ -13,7 +13,7 @@ Une même réalité métier possède une seule projection canonique. Lorsqu’un ## Metaplex Token Metadata -`materialize_metaplex_metadata_snapshot` matérialise un `CanonicalMetadataAccountSnapshot` de type `MetadataV1` lorsque sa provenance est commitée. +`materialize_metaplex_metadata_snapshot` matérialise un `DcMetadataMtmCanonicalMetadataAccountSnapshot` de type `MetadataV1` lorsque sa provenance est commitée. La projection conserve notamment : @@ -32,7 +32,7 @@ Une provenance non commitée ou un autre layout est refusé. ## Token-2022 incorporé -`materialize_token_2022_metadata_snapshot` projette uniquement les extensions `TokenMetadata`, `TokenGroup` et `TokenGroupMember` d’un état Mint déjà parsé et borné. La provenance reste `token_2022_embedded_tlv`; aucun URI externe n’est téléchargé et aucune donnée Metaplex n’est fusionnée implicitement. +`materialize_token2022_metadata_snapshot` projette uniquement les extensions `TokenMetadata`, `TokenGroup` et `TokenGroupMember` d’un état Mint déjà parsé et borné. La provenance reste `token_2022_embedded_tlv`; aucun URI externe n’est téléchargé et aucune donnée Metaplex n’est fusionnée implicitement. Les conflits éventuels entre Metaplex, Token-2022 embedded metadata et futures sources externes doivent être résolus par une politique de provenance explicite, jamais par écrasement silencieux. diff --git a/migration/khadhroony-bot2-reference/kb_model/README.md b/migration/khadhroony-bot2-reference/kb_model/README.md index d07762a..b733e48 100644 --- a/migration/khadhroony-bot2-reference/kb_model/README.md +++ b/migration/khadhroony-bot2-reference/kb_model/README.md @@ -18,7 +18,7 @@ Ce module fait partie du découpage strict de Khadhroony Bot2. Il doit conserver ## Contrat canonique `0.3.2` -Le crate expose maintenant `CanonicalTransaction` et les structures associées pour représenter une transaction Solana indépendamment de sa source. Le contrat couvre les transactions legacy et v0, les comptes statiques et chargés par ALT, les instructions externes et internes, les logs, les balances SOL/SPL, les erreurs, rewards, return data, compute units et block time. +Le crate expose maintenant `MdCanonicalTransaction` et les structures associées pour représenter une transaction Solana indépendamment de sa source. Le contrat couvre les transactions legacy et v0, les comptes statiques et chargés par ALT, les instructions externes et internes, les logs, les balances SOL/SPL, les erreurs, rewards, return data, compute units et block time. La sérialisation canonique : diff --git a/migration/khadhroony-bot2-reference/kb_pipeline/README.md b/migration/khadhroony-bot2-reference/kb_pipeline/README.md index 5344097..a2f5dd1 100644 --- a/migration/khadhroony-bot2-reference/kb_pipeline/README.md +++ b/migration/khadhroony-bot2-reference/kb_pipeline/README.md @@ -36,7 +36,7 @@ Le crate expose `execute_http_backfill`, `BackfillRequest`, `BackfillSource` et ## Replay decode `0.4.0` `execute_decode_replay` sélectionne des instructions core contextualisées par signatures, états, slots, program IDs et instruction paths. Il applique un dispatch déterministe, une concurrence bornée, l’arrêt coopératif, le skip processor/version/hash, un force replay obligatoirement borné par signatures ou par autorisation « toutes les signatures », et la persistance atomique via `DecodePipelineStore`. -Depuis `0.4.1-pre.014`, le contrat core `2` ajoute les instructions outer ordonnées au calcul de `contextual_input_hash`. `DECODE_PIPELINE_VERSION` reste `1` : le changement de contrat est déjà versionné et force naturellement un nouveau hash. Après application du delta, un force replay est nécessaire pour remplacer les résultats calculés avec le contrat `1`. Les transactions, rollbacks et clés d’idempotence du pipeline restent inchangés. +Depuis `0.4.1-pre.014`, le contrat core `2` ajoute les instructions outer ordonnées au calcul de `decoder_api_decoder_api_contextual_input_hash`. `DECODE_PIPELINE_VERSION` reste `1` : le changement de contrat est déjà versionné et force naturellement un nouveau hash. Après application du delta, un force replay est nécessaire pour remplacer les résultats calculés avec le contrat `1`. Les transactions, rollbacks et clés d’idempotence du pipeline restent inchangés. La matérialisation reste optionnelle, exige au moins un matérialiseur enregistré et n’est appelée qu’après la persistance réussie du décodage. Depuis `0.4.1-pre.005`, la sélection vérifie d’abord l’applicabilité exacte surface/entrée ; les observations de même famille mais hors périmètre ne créent plus de faux refus. Le résumé distingue les statuts par processor, les skips, les sorties matérialisées et les refus de politique. diff --git a/migration/khadhroony-bot2-reference/kb_store_core/README.md b/migration/khadhroony-bot2-reference/kb_store_core/README.md index 9164430..5350e2f 100644 --- a/migration/khadhroony-bot2-reference/kb_store_core/README.md +++ b/migration/khadhroony-bot2-reference/kb_store_core/README.md @@ -71,7 +71,7 @@ Les premiers contrats stabilisés sont volontairement minimaux : | `CoreInnerInstructionInsert` | Instruction CPI résolue avec parent, chemin et hash de payload. | | `CoreLogInsert` | Log ordonné avec rattachement prudent et hash de texte. | | `CoreBalanceChangeInsert` | Delta SOL ou token exact, déterministe et lié au compte résolu. | -| `CoreInstructionReplayInput` | Instruction avec contexte extrait, dont les instructions outer ordonnées depuis le contrat `2`, pour les décodeurs. | +| `MdCoreInstructionReplayInput` | Instruction avec contexte extrait, dont les instructions outer ordonnées depuis le contrat `2`, pour les décodeurs. | | `CoreInstructionReplayFilter` | Filtre de sélection des instructions à traiter ou rejouer. | | `CoreInstructionLifecycleMark` | Marquage d'état pour une instruction normalisée. | | `CoreInstructionProcessingState` | État opérationnel d'une instruction pour replay partiel. | @@ -181,12 +181,12 @@ kb_sol_ops_processing_ledger Le replay opérationnel doit pouvoir cibler `CoreInstructionRow`, pas seulement `CoreTransactionRow`. Cela permet à un décodeur de demander uniquement les instructions `Pending`, `Failed` ou `ReplayRequested`, filtrées par `program_id` et plage de slots. -Le décodage réel doit ensuite recevoir `CoreInstructionReplayInput`, c'est-à-dire une instruction avec son contexte extrait : comptes résolus, inner instructions, logs, balances et erreur de transaction. Cette décision prépare les futures tables `kb_sol_core_instructions`, `kb_sol_core_logs`, `kb_sol_core_balance_changes` et `kb_sol_ops_processing_ledger` sans figer encore leur SQL exact. +Le décodage réel doit ensuite recevoir `MdCoreInstructionReplayInput`, c'est-à-dire une instruction avec son contexte extrait : comptes résolus, inner instructions, logs, balances et erreur de transaction. Cette décision prépare les futures tables `kb_sol_core_instructions`, `kb_sol_core_logs`, `kb_sol_core_balance_changes` et `kb_sol_ops_processing_ledger` sans figer encore leur SQL exact. ## Extension `0.2.4` -`0.2.4` rend les contrats core effectivement utilisés par `kb_store_pg`. Le replay reste planifié depuis `CoreInstructionRow`, mais les décodeurs reçoivent `CoreInstructionReplayInput` avec account keys, inner instructions, logs et balance changes. +`0.2.4` rend les contrats core effectivement utilisés par `kb_store_pg`. Le replay reste planifié depuis `CoreInstructionRow`, mais les décodeurs reçoivent `MdCoreInstructionReplayInput` avec account keys, inner instructions, logs et balance changes. Le champ `balance_change_index` est ajouté au contrat `CoreBalanceChangeInsert` afin de dédupliquer les balance changes par ordre d'extraction dans une transaction. @@ -217,6 +217,6 @@ La couverture machine-readable est portée par `DecodeCoverageDeclarationInsert` ## Contrat contextualisé `2` -Depuis `0.4.1-pre.014`, `CoreInstructionReplayInput` transporte `outer_instructions_json`, obligatoirement un tableau JSON. Chaque entrée représente une instruction outer avec `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. La liste inclut l’instruction cible et conserve l’ordre numérique du message. Ce champ participe à la sérialisation déterministe et donc au hash de replay. +Depuis `0.4.1-pre.014`, `MdCoreInstructionReplayInput` transporte `outer_instructions_json`, obligatoirement un tableau JSON. Chaque entrée représente une instruction outer avec `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. La liste inclut l’instruction cible et conserve l’ordre numérique du message. Ce champ participe à la sérialisation déterministe et donc au hash de replay. Ce changement est purement contractuel : il ne requiert aucune migration SQL et ne modifie pas les garanties d’idempotence ou de rollback des stores. diff --git a/migration/khadhroony-bot2-reference/kb_store_pg/README.md b/migration/khadhroony-bot2-reference/kb_store_pg/README.md index b57f152..b913ed9 100644 --- a/migration/khadhroony-bot2-reference/kb_store_pg/README.md +++ b/migration/khadhroony-bot2-reference/kb_store_pg/README.md @@ -193,7 +193,7 @@ Le repository `CoreTransactionStore` est implémenté pour : - insérer les logs ordonnés ; - insérer les balance changes ; - lister les instructions à rejouer ; -- construire `CoreInstructionReplayInput` avec contexte, dont toutes les instructions outer de la signature ordonnées par index numérique ; +- construire `MdCoreInstructionReplayInput` avec contexte, dont toutes les instructions outer de la signature ordonnées par index numérique ; - marquer le lifecycle d'une instruction. ## Baseline canonique `0.3.1` diff --git a/migration/khadhroony-bot2-reference/prompts/005_v0_2_2_pg_connection_migrations.md b/migration/khadhroony-bot2-reference/prompts/005_v0_2_2_pg_connection_migrations.md index c1804d3..450d9c1 100644 --- a/migration/khadhroony-bot2-reference/prompts/005_v0_2_2_pg_connection_migrations.md +++ b/migration/khadhroony-bot2-reference/prompts/005_v0_2_2_pg_connection_migrations.md @@ -21,7 +21,7 @@ Ajouter uniquement l'infrastructure PostgreSQL : - diagnostic du schema courant ; - tests offline autant que possible. -Ne pas créer encore les tables Solana finales. Les premières tables réelles restent prévues pour `0.2.3` et `0.2.4`. Les migrations doivent cependant rester compatibles avec les contrats `CoreInstructionReplayInput`, `CoreLogInsert`, `CoreAccountKeyInsert` et `CoreBalanceChangeInsert`. +Ne pas créer encore les tables Solana finales. Les premières tables réelles restent prévues pour `0.2.3` et `0.2.4`. Les migrations doivent cependant rester compatibles avec les contrats `MdCoreInstructionReplayInput`, `CoreLogInsert`, `CoreAccountKeyInsert` et `CoreBalanceChangeInsert`. ## Règle PostgreSQL obligatoire diff --git a/migration/khadhroony-bot2-reference/prompts/019_v0_4_0_decoder_infrastructure.md b/migration/khadhroony-bot2-reference/prompts/019_v0_4_0_decoder_infrastructure.md index 211056f..6c4276d 100644 --- a/migration/khadhroony-bot2-reference/prompts/019_v0_4_0_decoder_infrastructure.md +++ b/migration/khadhroony-bot2-reference/prompts/019_v0_4_0_decoder_infrastructure.md @@ -57,7 +57,7 @@ Le contrat de décodage doit fournir au minimum : - changements de balances pertinents ; - version du contrat core. -Réutiliser ou faire évoluer `CoreInstructionReplayInput` au lieu de recréer un modèle parallèle par décodeur. +Réutiliser ou faire évoluer `MdCoreInstructionReplayInput` au lieu de recréer un modèle parallèle par décodeur. ### Transactions échouées diff --git a/migration/khadhroony-bot2-reference/prompts/022_v0_4_3_spl_memo.md b/migration/khadhroony-bot2-reference/prompts/022_v0_4_3_spl_memo.md index a1cb43f..f052f69 100644 --- a/migration/khadhroony-bot2-reference/prompts/022_v0_4_3_spl_memo.md +++ b/migration/khadhroony-bot2-reference/prompts/022_v0_4_3_spl_memo.md @@ -103,7 +103,7 @@ Respecter strictement : - aucun `bincode` direct ; - aucune logique métier lourde dans `kb_app_demo` ; - `CHANGELOG.md` inchangé avant validation complète du jalon ; -- `TRACING_TARGET` canonique dans `src/constants.rs` pour toute crate opérationnelle ; +- `DC_METADATA_MTM_TRACING_TARGET` canonique dans `src/constants.rs` pour toute crate opérationnelle ; - aucune valeur JSON Tauri exportée en `bigint` lorsqu'elle traverse `invoke`, `emit` ou `JSON.stringify`. ## 7. Audit préalable obligatoire diff --git a/migration/khadhroony-bot2-reference/prompts/023_v0_4_4_spl_token.md b/migration/khadhroony-bot2-reference/prompts/023_v0_4_4_spl_token.md index 7cb4ea5..62ea26c 100644 --- a/migration/khadhroony-bot2-reference/prompts/023_v0_4_4_spl_token.md +++ b/migration/khadhroony-bot2-reference/prompts/023_v0_4_4_spl_token.md @@ -125,7 +125,7 @@ Respecter strictement : - aucun `bincode` direct ; - aucune logique métier lourde dans `kb_app_demo` ; - `CHANGELOG.md` inchangé avant validation complète de `0.4.4` ; -- `TRACING_TARGET` canonique dans `src/constants.rs` pour toute crate opérationnelle ; +- `DC_METADATA_MTM_TRACING_TARGET` canonique dans `src/constants.rs` pour toute crate opérationnelle ; - aucune valeur JSON Tauri exportée en `bigint` lorsqu’elle traverse `invoke`, `emit` ou `JSON.stringify` ; - montants on-chain bruts sérialisés sans perte, sous forme de chaîne à la frontière Tauri si nécessaire. diff --git a/scripts/audit_khadhroony_workspace_rules.py b/scripts/audit_khadhroony_workspace_rules.py index f717853..d37608d 100755 --- a/scripts/audit_khadhroony_workspace_rules.py +++ b/scripts/audit_khadhroony_workspace_rules.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # file: scripts/audit_khadhroony_workspace_rules.py -# version: 3 +# version: 4 """Audit mechanically verifiable rules specific to khadhroony-bot3.""" @@ -90,13 +90,16 @@ def audit_kb_lib_tracing(root: pathlib.Path) -> list[Violation]: if not crate_root.exists(): return violations root_text = crate_root.read_text(encoding="utf-8") - aliases = set( - re.findall( - r"^pub\(crate\) use crate::[A-Za-z0-9_:]+::([A-Z][A-Z0-9_]+_TRACING_TARGET);$", - root_text, - re.MULTILINE, - ) + aliases = set() + alias_pattern = re.compile( + r"^pub\(crate\) use crate::[A-Za-z0-9_:]+::" + r"([A-Z][A-Z0-9_]+)(?: as ([A-Z][A-Z0-9_]+))?;$", + re.MULTILINE, ) + for match in alias_pattern.finditer(root_text): + exported_name = match.group(2) if match.group(2) is not None else match.group(1) + if exported_name.endswith("_TRACING_TARGET"): + aliases.add(exported_name) target_pattern = re.compile( r'^pub\(crate\) const TRACING_TARGET: &str = "([^"]+)";$', re.MULTILINE, diff --git a/scripts/audit_rust_general_rules.py b/scripts/audit_rust_general_rules.py index 174c528..70a828b 100755 --- a/scripts/audit_rust_general_rules.py +++ b/scripts/audit_rust_general_rules.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # file: scripts/audit_rust_general_rules.py -# version: 3 +# version: 4 """Audit mechanically verifiable Rust rules shared by all Rust projects.""" @@ -54,6 +54,18 @@ def audit_file(root: pathlib.Path, path: pathlib.Path) -> list[Violation]: violations.append(Violation("RUST003", relative, max(len(lines), 1), "file must end with exactly one newline")) for index, line in enumerate(lines, 1): stripped = line.strip() + if stripped.startswith("pub mod ") and ( + relative == "kb-lib/src/lib.rs" and stripped == "pub mod materializer;" + or relative.startswith("kb-lib/src/materializer") + ): + violations.append( + Violation( + "RUST014", + relative, + index, + "consolidated materializer modules must remain private", + ) + ) if re.match(r"^(?:pub(?:\(crate\))?\s+)?use\s+", stripped) is None: continue is_export = stripped.startswith("pub use ") or stripped.startswith("pub(crate) use ") @@ -70,12 +82,30 @@ def audit_file(root: pathlib.Path, path: pathlib.Path) -> list[Violation]: for attribute in ("#![warn(missing_docs)]", "#![deny(unreachable_pub)]", "#![forbid(unsafe_code)]"): if attribute not in lines[:20]: violations.append(Violation("RUST020", relative, 1, f"missing `{attribute}`")) + previous_export_line: int | None = None + previous_export_visibility: str | None = None for index, line in enumerate(lines, 1): if not (line.startswith("pub use ") or line.startswith("pub(crate) use ")): continue previous = lines[index - 2].strip() if index >= 2 else "" if not previous.startswith("///"): violations.append(Violation("RUST021", relative, index, "crate-root re-export requires adjacent rustdoc")) + visibility = "pub(crate)" if line.startswith("pub(crate) use ") else "pub" + if ( + previous_export_line is not None + and previous_export_visibility == visibility + and any(not candidate.strip() for candidate in lines[previous_export_line:index - 1]) + ): + violations.append( + Violation( + "RUST022", + relative, + index, + "crate-root re-export block contains an empty line", + ) + ) + previous_export_line = index + previous_export_visibility = visibility return violations