This commit is contained in:
2026-07-23 16:37:12 +02:00
parent 99c345f2f2
commit 0da75c1311
2159 changed files with 230833 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
# file: kb_executor_spl_token_2022/Cargo.toml
# version: 5
[package]
name = "kb_executor_spl_token_2022"
version.workspace = true
edition.workspace = true
license.workspace = true
publish.workspace = true
[dependencies]
bytemuck.workspace = true
kb_core = { path = "../kb_core" }
kb_execution_api = { path = "../kb_execution_api" }
kb_execution_safety = { path = "../kb_execution_safety" }
kb_model = { path = "../kb_model" }
kb_program_ids = { path = "../kb_program_ids" }
serde.workspace = true
serde_json.workspace = true
solana-instruction.workspace = true
solana-pubkey.workspace = true
solana-zk-sdk-pod.workspace = true
solana-zk-elgamal-proof-interface.workspace = true
spl-token-confidential-transfer-proof-extraction.workspace = true
spl-token-2022-interface.workspace = true
spl-token-metadata-interface.workspace = true
spl-token-group-interface.workspace = true
tracing.workspace = true
ts-rs.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,139 @@
<!-- file: kb_executor_spl_token_2022/README.md -->
<!-- version: 13 -->
# kb_executor_spl_token_2022
Ce crate construit des plans dexécution typés pour le programme SPL Token-2022. Il ne diffuse aucune transaction directement : lorchestration impose simulation, plafonds de coûts, signataires autorisés et validation post-exécution.
## Frontière
- Program ID exact : `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`.
- Builders officiels de `spl-token-2022-interface`.
- Clés publiques exposées par `solana_pubkey::Pubkey` via les contrats `kb_model`.
- `Batch` reste decode-only tant quaucun builder officiel nest publié.
- Les opérations confidentielles restent séparées jusquà validation complète des preuves et comptes de contexte.
## Transfer Fee
La tranche `0.4.6-pre.043` ajoute les six builders publics officiels :
- `initialize_transfer_fee_config` ;
- `set_transfer_fee` ;
- `transfer_checked_with_fee` ;
- `withdraw_withheld_tokens_from_mint` ;
- `withdraw_withheld_tokens_from_accounts` ;
- `harvest_withheld_tokens_to_mint`.
Les montants restent des chaînes décimales `u64`. Les basis points sont limités à `10_000`. Les listes de comptes sources sont non vides, uniques, ordonnées et limitées à 255 occurrences. Les autorités simples et multisig conservent exactement les metas publiées par linterface officielle.
## Default Account State, Memo Transfer et CPI Guard
La tranche `0.4.6-pre.044` ajoute les six builders publics officiels :
- `initialize_default_account_state` ;
- `update_default_account_state` ;
- `enable_required_transfer_memos` ;
- `disable_required_transfer_memos` ;
- `enable_cpi_guard` ;
- `disable_cpi_guard`.
`InitializeDefaultAccountState` doit précéder l'initialisation du mint. La mise à jour utilise la freeze authority, simple ou multisig. Memo Transfer et CPI Guard modifient un Token Account et utilisent son owner, simple ou multisig. Les états par défaut sont typés `initialized` ou `frozen`; aucune valeur numérique arbitraire n'est acceptée.
## Transfer Hook et pointers
La tranche `0.4.6-pre.045` ajoute les huit builders publics officiels :
- `initialize_transfer_hook` et `update_transfer_hook` ;
- `initialize_metadata_pointer` et `update_metadata_pointer` ;
- `initialize_group_pointer` et `update_group_pointer` ;
- `initialize_group_member_pointer` et `update_group_member_pointer`.
Les initialisations doivent précéder l'initialisation du mint et acceptent une autorité optionnelle ainsi qu'une cible optionnelle. Les mises à jour utilisent une autorité simple ou multisig et acceptent `None` pour supprimer explicitement la cible. Les metas et l'ordre des signataires proviennent exclusivement des builders officiels de `spl-token-2022-interface`.
## Sécurité
- simulation obligatoire ;
- dry-run par défaut ;
- plafond de frais positif obligatoire ;
- matérialisation post-exécution requise pour les mutations ;
- aucun calcul de fee implicite : `transfer_checked_with_fee` exige le montant attendu exact ;
- aucun retrait ou harvest ninvente létat final, qui doit être relu par le pipeline stateful.
## Token Metadata et Token Group
La tranche `0.4.6-pre.046` ajoute les builders officiels des interfaces exécutées sous le Program ID Token-2022 :
- initialisation, mise à jour de champ et suppression de clé Token Metadata ;
- initialisation de groupe, mise à jour de `max_size` et initialisation de membre ;
- chaînes metadata bornées à 1 024 octets par champ dans le contrat dexécution ;
- comptes et signataires conservés dans lordre publié par les interfaces ;
- aucune confusion avec Metaplex Token Metadata ni avec une implémentation tierce des interfaces.
Les instructions utilisent les discriminateurs SPL des interfaces et non un tag `TokenInstruction` sur un octet. Le dispatcher reste strictement attaché au Program ID Token-2022 pour cette crate.
## Extensions publiques récentes
Lexécuteur construit désormais les opérations officielles `ScaledUiAmount`, `Pausable` et `PermissionedBurn`. Les multiplicateurs Scaled UI sont fournis sous forme de chaîne décimale, puis refusés sils ne sont pas strictement positifs, finis et normaux. `PermissionedBurn` conserve séparément lautorité dédiée obligatoire et lowner/delegate simple ou multisig du compte source. Les opérations confidentielles de burn restent hors de cette tranche.
## Audit Confidential Transfer
La tranche `0.4.6-pre.048` publie uniquement le contrat audité des opérations confidentielles : inventaire des opérations, ordre exact des preuves, modes `instruction_offset` et `context_state_account`, et classification entre builders ne nécessitant que des données publiques et opérations exigeant des entrées cryptographiques générées par lappelant.
Un offset inline nul est refusé : la valeur wire `0` est réservée au mode compte de contexte. Les instructions Token-2022, les instructions du programme ZK ElGamal Proof et les instructions du registre ElGamal restent trois surfaces techniques distinctes. Aucun chiffrement, déchiffrement, secret ou preuve nest généré par ce crate.
## Confidential Transfer public-data builders
The executor constructs the six Confidential Transfer operations whose complete wire payload is public and requires no caller-generated proof or ciphertext: account approval, public deposit, and the four credit toggles. Initialize/update mint and apply-pending-balance remain deferred because their official data contracts include ElGamal or decryptable-balance material that must be supplied as bounded opaque caller input.
## Confidential Transfer — entrées cryptographiques opaques
Lexécuteur accepte désormais les clés publiques ElGamal de 32 octets et les balances déchiffrables de 36 octets sous forme hexadécimale stricte. Il construit `InitializeMint`, `UpdateMint` et `ApplyPendingBalance` avec les builders officiels, sans générer ni dériver de secret.
## Configuration confidentielle des comptes
`ConfigureConfidentialTransferAccount` accepte une balance zéro déchiffrable opaque, un compteur maximal de crédits en attente, une autorité simple ou multisig et une référence `PubkeyValidity` explicite. Le mode `InstructionOffset` référence une instruction ZK déjà orchestrée dans la transaction ; le mode `ContextStateAccount` référence un contexte pré-vérifié. Le crate ne fabrique aucune preuve.
`ConfigureConfidentialTransferAccountWithRegistry` utilise un compte ElGamal Registry explicite. Le payer de réallocation est optionnel ; lorsquil est présent, le builder officiel ajoute le System Program. La cohérence owner/PDA du registre reste un préflight obligatoire avant diffusion.
## Confidential Transfer — vidage du compte
`EmptyConfidentialTransferAccount` construit linstruction Token-2022 `EmptyAccount` avec une référence `ZeroCiphertext` explicite. Le mode `InstructionOffset` ajoute uniquement le compte Instructions Sysvar et encode loffset signé non nul ; le mode `ContextStateAccount` ajoute le compte de contexte readonly et encode loffset `0`. Lautorité owner/delegate simple ou multisig reste ordonnée exactement. Le crate ne génère ni preuve ni donnée secrète.
`WithdrawConfidentialTokens` construit linstruction `Withdraw` avec montant brut, decimals, nouvelle balance déchiffrable opaque et deux preuves ordonnées : `CiphertextCommitmentEquality`, puis `BatchedRangeProofU64`. Chaque preuve peut être référencée par offset inline non nul ou par compte context-state ; le compte Instructions Sysvar nest ajouté quune seule fois lorsquau moins une preuve est inline.
## Transfer confidentiel
`TransferConfidentialTokens` construit l'instruction Token-2022 `ConfidentialTransferExtension::Transfer` avec une balance source déchiffrable de 36 octets, deux ciphertexts auditeur ElGamal de 64 octets et trois preuves référencées dans l'ordre officiel : Equality, Grouped Ciphertext Validity à trois handles, puis Range U128. Les preuves peuvent utiliser indépendamment un offset inline non nul ou un compte context-state. Le crate ne génère aucun ciphertext, secret ou preuve.
## Audit Transfer With Fee (`pre.055`)
Le contrat audité fixe le wire `27/13`, 169 octets de payload et 171 octets de données dinstruction. Le payload Token-2022 réutilise uniquement `SplTokenDecryptableBalance` et deux `SplTokenElGamalCiphertext`. Le ciphertext de frais et les paramètres de frais restent portés par les contextes de preuve, pas par un nouveau champ opaque de lintent Token-2022.
### Transfer confidentiel avec frais
`TransferConfidentialTokensWithFee` construit linstruction Token-2022 `ConfidentialTransferExtension::TransferWithFee` avec cinq références de preuve strictement ordonnées : equality, validité trois handles, percentage with fee, validité deux handles et range U256. Chaque preuve peut être référencée par offset non nul ou par compte context-state. Le crate valide uniquement les entrées opaques fournies ; il ne produit aucune preuve ni donnée secrète.
## Confidential Transfer Fee public operations (`pre.057`)
The executor constructs the four proof-free public operations published by
`spl-token-2022-interface 3.1.1`:
- initialize confidential transfer fee configuration before mint initialization;
- enable harvest to mint;
- disable harvest to mint;
- permissionless harvest of ordered, distinct source accounts to the mint.
The initialization keeps the optional configuration authority and the exact
caller-provided 32-byte ElGamal public key. Harvest source lists use the same
non-empty, unique and `u8`-bounded contract as public transfer-fee harvests.
No ciphertext is decrypted or synthesized.
- `withdraw_confidential_withheld_tokens_from_mint` : retrait depuis le Mint avec preuve `CiphertextCiphertextEquality` inline ou context-state.
## Confidential Transfer Fee — retrait multi-comptes (`pre.059`)
`WithdrawConfidentialWithheldTokensFromAccounts` construit le retrait direct des frais confidentiels depuis une liste ordonnée de Token Accounts vers un compte destination Confidential Transfer. Le Mint reste readonly, la destination est writable, puis viennent la référence de preuve, lautorité withdraw-withheld, les signataires multisig et enfin les sources writable.
La liste de sources doit être non vide, unique et limitée à 255 comptes. Le nombre exact est encodé sur `u8` dans le payload. La preuve exigée est `CiphertextCiphertextEquality`, référencée par offset inline non nul ou par compte context-state. Cette opération est sensible au front-running : tout changement dun withheld ciphertext source entre la génération de la preuve et lexécution invalide la preuve. Le parcours recommandé pour réduire ce risque reste harvest vers Mint puis retrait depuis le Mint.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,576 @@
// file: kb_executor_spl_token_2022/src/confidential.rs
// version: 8
//! Audited Confidential Transfer execution contracts.
use ts_rs::TS; // rust-rules: derive-import
/// Maximum number of proof references accepted by one confidential operation.
pub const MAX_CONFIDENTIAL_PROOF_REFERENCES: usize = 5;
/// Exact byte length of an ElGamal public key accepted from callers.
pub const ELGAMAL_PUBKEY_BYTES: usize = 32;
/// Exact byte length of one decryptable authenticated balance ciphertext.
pub const DECRYPTABLE_BALANCE_BYTES: usize = 36;
/// Exact byte length of one ElGamal ciphertext accepted from callers.
pub const ELGAMAL_CIPHERTEXT_BYTES: usize = 64;
/// Token-2022 outer tag shared by all Confidential Transfer instructions.
pub const CONFIDENTIAL_TRANSFER_EXTERNAL_TAG: u8 = 27;
/// Confidential Transfer subtag published for `TransferWithFee`.
pub const CONFIDENTIAL_TRANSFER_WITH_FEE_SUBTAG: u8 = 13;
/// Exact payload bytes after the two instruction discriminants for `TransferWithFee`.
pub const CONFIDENTIAL_TRANSFER_WITH_FEE_PAYLOAD_BYTES: usize =
DECRYPTABLE_BALANCE_BYTES + (ELGAMAL_CIPHERTEXT_BYTES * 2) + MAX_CONFIDENTIAL_PROOF_REFERENCES;
/// Exact total Token-2022 instruction-data bytes for `TransferWithFee`.
pub const CONFIDENTIAL_TRANSFER_WITH_FEE_INSTRUCTION_DATA_BYTES: usize =
2 + CONFIDENTIAL_TRANSFER_WITH_FEE_PAYLOAD_BYTES;
/// Caller-generated ElGamal public key encoded as lowercase or uppercase hexadecimal.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenElGamalPubkey.ts"
)]
pub struct SplTokenElGamalPubkey(pub std::string::String);
impl SplTokenElGamalPubkey {
pub(crate) fn parse(
&self,
) -> Result<solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, std::string::String> {
let bytes = match decode_exact_hex(&self.0, ELGAMAL_PUBKEY_BYTES, "ElGamal public key") {
Ok(value) => value,
Err(error) => return Err(error),
};
let array = match <[u8; ELGAMAL_PUBKEY_BYTES]>::try_from(bytes.as_slice()) {
Ok(value) => value,
Err(_) => return Err("ElGamal public key has an invalid length".to_owned()),
};
return Ok(bytemuck::pod_read_unaligned(array.as_slice()));
}
}
/// Caller-generated decryptable balance encoded as hexadecimal bytes.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenDecryptableBalance.ts"
)]
pub struct SplTokenDecryptableBalance(pub std::string::String);
impl SplTokenDecryptableBalance {
pub(crate) fn parse(
&self,
) -> Result<solana_zk_sdk_pod::encryption::auth_encryption::PodAeCiphertext, std::string::String>
{
let bytes =
match decode_exact_hex(&self.0, DECRYPTABLE_BALANCE_BYTES, "decryptable balance") {
Ok(value) => value,
Err(error) => return Err(error),
};
let array = match <[u8; DECRYPTABLE_BALANCE_BYTES]>::try_from(bytes.as_slice()) {
Ok(value) => value,
Err(_) => return Err("decryptable balance has an invalid length".to_owned()),
};
return Ok(bytemuck::pod_read_unaligned(array.as_slice()));
}
}
/// Caller-generated ElGamal ciphertext encoded as hexadecimal bytes.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenElGamalCiphertext.ts"
)]
pub struct SplTokenElGamalCiphertext(pub std::string::String);
impl SplTokenElGamalCiphertext {
pub(crate) fn parse(
&self,
) -> Result<solana_zk_sdk_pod::encryption::elgamal::PodElGamalCiphertext, std::string::String>
{
let bytes = match decode_exact_hex(&self.0, ELGAMAL_CIPHERTEXT_BYTES, "ElGamal ciphertext")
{
Ok(value) => value,
Err(error) => return Err(error),
};
let array = match <[u8; ELGAMAL_CIPHERTEXT_BYTES]>::try_from(bytes.as_slice()) {
Ok(value) => value,
Err(_) => return Err("ElGamal ciphertext has an invalid length".to_owned()),
};
return Ok(bytemuck::pod_read_unaligned(array.as_slice()));
}
}
fn decode_exact_hex(
value: &str,
expected_bytes: usize,
label: &str,
) -> Result<std::vec::Vec<u8>, std::string::String> {
if value.len() != expected_bytes.saturating_mul(2) {
return Err(format!(
"{label} must contain exactly {expected_bytes} bytes encoded as hexadecimal"
));
}
let input = value.as_bytes();
let mut output = std::vec::Vec::with_capacity(expected_bytes);
let mut index = 0usize;
while index < input.len() {
let high = match decode_hex_nibble(input[index]) {
Some(v) => v,
None => return Err(format!("{label} contains a non-hexadecimal character")),
};
let low = match decode_hex_nibble(input[index + 1]) {
Some(v) => v,
None => return Err(format!("{label} contains a non-hexadecimal character")),
};
output.push((high << 4) | low);
index += 2;
}
return Ok(output);
}
fn decode_hex_nibble(value: u8) -> Option<u8> {
return match value {
b'0'..=b'9' => Some(value - b'0'),
b'a'..=b'f' => Some(value - b'a' + 10),
b'A'..=b'F' => Some(value - b'A' + 10),
_ => None,
};
}
/// Proof statement required by a Confidential Transfer operation.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenConfidentialProofKind.ts"
)]
pub enum SplTokenConfidentialProofKind {
/// ElGamal public-key validity.
PubkeyValidity,
/// Zero-ciphertext proof used before account closure.
ZeroCiphertext,
/// Ciphertext-commitment equality.
CiphertextCommitmentEquality,
/// Ciphertext-ciphertext equality used by confidential fee withdrawals.
CiphertextCiphertextEquality,
/// Batched grouped-ciphertext validity with three decryption handles.
BatchedGroupedCiphertext3HandlesValidity,
/// Batched grouped-ciphertext validity with two decryption handles.
BatchedGroupedCiphertext2HandlesValidity,
/// Percentage-with-fee sigma proof.
PercentageWithFee,
/// Batched 64-bit range proof.
BatchedRangeProofU64,
/// Batched 128-bit range proof.
BatchedRangeProofU128,
/// Batched 256-bit range proof.
BatchedRangeProofU256,
}
/// Explicit source for one already-generated zero-knowledge proof statement.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case", tag = "mode")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenConfidentialProofLocation.ts"
)]
pub enum SplTokenConfidentialProofLocation {
/// Relative transaction offset of a separate ZK proof-program instruction.
InstructionOffset {
/// Non-zero signed relative instruction offset.
offset: i8,
},
/// Account containing a previously verified proof context state.
ContextStateAccount {
/// Proof context-state account.
account: kb_model::Pubkey,
},
}
impl SplTokenConfidentialProofLocation {
/// Validates the mode-specific proof-location contract.
pub fn validate(&self) -> Result<(), std::string::String> {
return match self {
Self::InstructionOffset { offset } if *offset == 0 => Err(
"an inline proof instruction offset must be non-zero; zero is reserved for a context-state account"
.to_owned(),
),
Self::InstructionOffset { .. } | Self::ContextStateAccount { .. } => Ok(()),
};
}
}
/// One proof requirement paired with its explicit location.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenConfidentialProofReference.ts"
)]
pub struct SplTokenConfidentialProofReference {
/// Exact proof statement required by the Token-2022 builder.
pub kind: SplTokenConfidentialProofKind,
/// Inline-instruction or context-state source.
pub location: SplTokenConfidentialProofLocation,
}
/// Audited Confidential Transfer operation surface.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenConfidentialOperation.ts"
)]
pub enum SplTokenConfidentialOperation {
/// Initialize confidential-transfer mint configuration.
InitializeMint,
/// Update confidential-transfer mint configuration.
UpdateMint,
/// Configure a token account with an ElGamal key.
ConfigureAccount,
/// Approve a configured account.
ApproveAccount,
/// Empty the available ciphertext before closing an account.
EmptyAccount,
/// Deposit public tokens into pending confidential balance.
Deposit,
/// Withdraw confidential balance into public balance.
Withdraw,
/// Transfer confidentially without a transfer fee.
Transfer,
/// Apply pending balance credits.
ApplyPendingBalance,
/// Enable confidential credits.
EnableConfidentialCredits,
/// Disable confidential credits.
DisableConfidentialCredits,
/// Enable non-confidential credits.
EnableNonConfidentialCredits,
/// Disable non-confidential credits.
DisableNonConfidentialCredits,
/// Transfer confidentially with fee proofs.
TransferWithFee,
/// Configure an account through an ElGamal Registry account.
ConfigureAccountWithRegistry,
}
impl SplTokenConfidentialOperation {
/// Returns the ordered proof statements required by the official builder.
pub fn required_proofs(&self) -> &'static [SplTokenConfidentialProofKind] {
return match self {
Self::ConfigureAccount | Self::ConfigureAccountWithRegistry => {
&[SplTokenConfidentialProofKind::PubkeyValidity]
},
Self::EmptyAccount => &[SplTokenConfidentialProofKind::ZeroCiphertext],
Self::Withdraw => &[
SplTokenConfidentialProofKind::CiphertextCommitmentEquality,
SplTokenConfidentialProofKind::BatchedRangeProofU64,
],
Self::Transfer => &[
SplTokenConfidentialProofKind::CiphertextCommitmentEquality,
SplTokenConfidentialProofKind::BatchedGroupedCiphertext3HandlesValidity,
SplTokenConfidentialProofKind::BatchedRangeProofU128,
],
Self::TransferWithFee => &[
SplTokenConfidentialProofKind::CiphertextCommitmentEquality,
SplTokenConfidentialProofKind::BatchedGroupedCiphertext3HandlesValidity,
SplTokenConfidentialProofKind::PercentageWithFee,
SplTokenConfidentialProofKind::BatchedGroupedCiphertext2HandlesValidity,
SplTokenConfidentialProofKind::BatchedRangeProofU256,
],
Self::InitializeMint
| Self::UpdateMint
| Self::ApproveAccount
| Self::Deposit
| Self::ApplyPendingBalance
| Self::EnableConfidentialCredits
| Self::DisableConfidentialCredits
| Self::EnableNonConfidentialCredits
| Self::DisableNonConfidentialCredits => &[],
};
}
/// Indicates whether the Token-2022 instruction can be constructed without secret material.
pub fn executor_support(&self) -> SplTokenConfidentialExecutorSupport {
return match self {
Self::InitializeMint
| Self::UpdateMint
| Self::ApproveAccount
| Self::Deposit
| Self::ApplyPendingBalance
| Self::EnableConfidentialCredits
| Self::DisableConfidentialCredits
| Self::EnableNonConfidentialCredits
| Self::DisableNonConfidentialCredits => {
SplTokenConfidentialExecutorSupport::PublicBuilderReady
},
Self::ConfigureAccount
| Self::EmptyAccount
| Self::Withdraw
| Self::Transfer
| Self::TransferWithFee
| Self::ConfigureAccountWithRegistry => {
SplTokenConfidentialExecutorSupport::RequiresCallerGeneratedCryptographicInputs
},
};
}
}
/// Audited Confidential Mint/Burn operation surface.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenConfidentialMintBurnOperation.ts"
)]
pub enum SplTokenConfidentialMintBurnOperation {
/// Initialize the mint extension with supply encryption material.
InitializeMint,
/// Rotate the supply ElGamal public key.
RotateSupplyElGamalPubkey,
/// Replace the caller-maintained decryptable supply.
UpdateDecryptableSupply,
/// Mint tokens directly into a confidential token account.
Mint,
/// Burn tokens from a confidential token account.
Burn,
/// Aggregate the pending burn ciphertext into confidential supply.
ApplyPendingBurn,
}
impl SplTokenConfidentialMintBurnOperation {
/// Returns the published subdiscriminant.
pub fn subtag(&self) -> u8 {
return match self {
Self::InitializeMint => 0,
Self::RotateSupplyElGamalPubkey => 1,
Self::UpdateDecryptableSupply => 2,
Self::Mint => 3,
Self::Burn => 4,
Self::ApplyPendingBurn => 5,
};
}
/// Returns the ordered proof statements required by the official builder.
pub fn required_proofs(&self) -> &'static [SplTokenConfidentialProofKind] {
return match self {
Self::RotateSupplyElGamalPubkey => {
&[SplTokenConfidentialProofKind::CiphertextCiphertextEquality]
},
Self::Mint | Self::Burn => &[
SplTokenConfidentialProofKind::CiphertextCommitmentEquality,
SplTokenConfidentialProofKind::BatchedGroupedCiphertext3HandlesValidity,
SplTokenConfidentialProofKind::BatchedRangeProofU128,
],
Self::InitializeMint | Self::UpdateDecryptableSupply | Self::ApplyPendingBurn => &[],
};
}
/// Classifies whether the caller must supply cryptographic material.
pub fn executor_support(&self) -> SplTokenConfidentialExecutorSupport {
return match self {
Self::UpdateDecryptableSupply | Self::ApplyPendingBurn => {
SplTokenConfidentialExecutorSupport::PublicBuilderReady
},
Self::InitializeMint | Self::RotateSupplyElGamalPubkey | Self::Mint | Self::Burn => {
SplTokenConfidentialExecutorSupport::RequiresCallerGeneratedCryptographicInputs
},
};
}
}
/// Executor-readiness classification established by the Confidential Transfer audit.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_token_2022/confidential/SplTokenConfidentialExecutorSupport.ts"
)]
pub enum SplTokenConfidentialExecutorSupport {
/// The builder needs only public fields and ordinary authorities.
PublicBuilderReady,
/// The caller must provide ciphertexts, decryptable balances and/or proof data generated outside this executor.
RequiresCallerGeneratedCryptographicInputs,
}
/// Validates an ordered proof-reference list against the audited operation contract.
pub fn validate_confidential_proof_references(
operation: SplTokenConfidentialOperation,
references: &[SplTokenConfidentialProofReference],
) -> Result<(), std::string::String> {
let required = operation.required_proofs();
if references.len() > MAX_CONFIDENTIAL_PROOF_REFERENCES {
return Err("too many confidential proof references".to_owned());
}
if references.len() != required.len() {
return Err(
"confidential proof reference count does not match the operation contract".to_owned()
);
}
for (index, reference) in references.iter().enumerate() {
if let Err(error) = reference.location.validate() {
return Err(error);
}
if reference.kind != required[index] {
return Err(
"confidential proof references are not in the official builder order".to_owned()
);
}
}
return Ok(());
}
#[cfg(test)]
mod tests {
#[test]
fn audit_partitions_public_builders_from_caller_generated_cryptographic_inputs() {
assert_eq!(
super::SplTokenConfidentialOperation::Deposit.executor_support(),
super::SplTokenConfidentialExecutorSupport::PublicBuilderReady
);
assert_eq!(
super::SplTokenConfidentialOperation::Transfer.executor_support(),
super::SplTokenConfidentialExecutorSupport::RequiresCallerGeneratedCryptographicInputs
);
assert_eq!(
super::SplTokenConfidentialOperation::ConfigureAccountWithRegistry.executor_support(),
super::SplTokenConfidentialExecutorSupport::RequiresCallerGeneratedCryptographicInputs
);
}
#[test]
fn opaque_public_inputs_require_exact_hex_lengths() {
let pubkey = super::SplTokenElGamalPubkey("11".repeat(super::ELGAMAL_PUBKEY_BYTES));
assert!(pubkey.parse().is_ok());
let balance =
super::SplTokenDecryptableBalance("22".repeat(super::DECRYPTABLE_BALANCE_BYTES));
assert!(balance.parse().is_ok());
assert!(super::SplTokenElGamalPubkey("00".repeat(31)).parse().is_err());
assert!(super::SplTokenDecryptableBalance("zz".repeat(36)).parse().is_err());
let ciphertext =
super::SplTokenElGamalCiphertext("33".repeat(super::ELGAMAL_CIPHERTEXT_BYTES));
assert!(ciphertext.parse().is_ok());
assert!(super::SplTokenElGamalCiphertext("33".repeat(63)).parse().is_err());
}
#[test]
fn proof_inventory_preserves_official_transfer_and_fee_order() {
assert_eq!(
super::SplTokenConfidentialOperation::Transfer.required_proofs(),
&[
super::SplTokenConfidentialProofKind::CiphertextCommitmentEquality,
super::SplTokenConfidentialProofKind::BatchedGroupedCiphertext3HandlesValidity,
super::SplTokenConfidentialProofKind::BatchedRangeProofU128,
]
);
assert_eq!(
super::SplTokenConfidentialOperation::TransferWithFee.required_proofs(),
&[
super::SplTokenConfidentialProofKind::CiphertextCommitmentEquality,
super::SplTokenConfidentialProofKind::BatchedGroupedCiphertext3HandlesValidity,
super::SplTokenConfidentialProofKind::PercentageWithFee,
super::SplTokenConfidentialProofKind::BatchedGroupedCiphertext2HandlesValidity,
super::SplTokenConfidentialProofKind::BatchedRangeProofU256,
]
);
}
#[test]
fn transfer_with_fee_audit_matches_official_wire_and_requires_no_extra_token_payload_ciphertext()
{
assert_eq!(super::CONFIDENTIAL_TRANSFER_EXTERNAL_TAG, 27);
assert_eq!(super::CONFIDENTIAL_TRANSFER_WITH_FEE_SUBTAG, 13);
assert_eq!(super::CONFIDENTIAL_TRANSFER_WITH_FEE_PAYLOAD_BYTES, 169);
assert_eq!(super::CONFIDENTIAL_TRANSFER_WITH_FEE_INSTRUCTION_DATA_BYTES, 171);
assert_eq!(
core::mem::size_of::<
spl_token_2022_interface::extension::confidential_transfer::instruction::TransferWithFeeInstructionData,
>(),
super::CONFIDENTIAL_TRANSFER_WITH_FEE_PAYLOAD_BYTES
);
assert_eq!(
super::SplTokenConfidentialOperation::TransferWithFee.required_proofs().len(),
super::MAX_CONFIDENTIAL_PROOF_REFERENCES
);
let decryptable_balance =
super::SplTokenDecryptableBalance("44".repeat(super::DECRYPTABLE_BALANCE_BYTES));
let auditor_ciphertext_lo =
super::SplTokenElGamalCiphertext("55".repeat(super::ELGAMAL_CIPHERTEXT_BYTES));
let auditor_ciphertext_hi =
super::SplTokenElGamalCiphertext("66".repeat(super::ELGAMAL_CIPHERTEXT_BYTES));
assert!(decryptable_balance.parse().is_ok());
assert!(auditor_ciphertext_lo.parse().is_ok());
assert!(auditor_ciphertext_hi.parse().is_ok());
}
#[test]
fn confidential_mint_burn_audit_matches_published_subtags_proofs_and_support() {
assert_eq!(super::SplTokenConfidentialMintBurnOperation::InitializeMint.subtag(), 0);
assert_eq!(
super::SplTokenConfidentialMintBurnOperation::RotateSupplyElGamalPubkey.subtag(),
1
);
assert_eq!(
super::SplTokenConfidentialMintBurnOperation::UpdateDecryptableSupply.subtag(),
2
);
assert_eq!(super::SplTokenConfidentialMintBurnOperation::Mint.subtag(), 3);
assert_eq!(super::SplTokenConfidentialMintBurnOperation::Burn.subtag(), 4);
assert_eq!(super::SplTokenConfidentialMintBurnOperation::ApplyPendingBurn.subtag(), 5);
assert_eq!(
super::SplTokenConfidentialMintBurnOperation::RotateSupplyElGamalPubkey
.required_proofs(),
&[super::SplTokenConfidentialProofKind::CiphertextCiphertextEquality]
);
assert_eq!(
super::SplTokenConfidentialMintBurnOperation::Mint.required_proofs(),
&[
super::SplTokenConfidentialProofKind::CiphertextCommitmentEquality,
super::SplTokenConfidentialProofKind::BatchedGroupedCiphertext3HandlesValidity,
super::SplTokenConfidentialProofKind::BatchedRangeProofU128,
]
);
assert_eq!(
super::SplTokenConfidentialMintBurnOperation::Burn.required_proofs(),
super::SplTokenConfidentialMintBurnOperation::Mint.required_proofs()
);
assert_eq!(
super::SplTokenConfidentialMintBurnOperation::ApplyPendingBurn.executor_support(),
super::SplTokenConfidentialExecutorSupport::PublicBuilderReady
);
assert_eq!(
super::SplTokenConfidentialMintBurnOperation::Mint.executor_support(),
super::SplTokenConfidentialExecutorSupport::RequiresCallerGeneratedCryptographicInputs
);
}
#[test]
fn proof_locations_keep_inline_and_context_state_modes_unambiguous() {
let context_account = kb_model::Pubkey("11111111111111111111111111111111".to_owned());
let references = vec![super::SplTokenConfidentialProofReference {
kind: super::SplTokenConfidentialProofKind::ZeroCiphertext,
location: super::SplTokenConfidentialProofLocation::ContextStateAccount {
account: context_account,
},
}];
assert!(
super::validate_confidential_proof_references(
super::SplTokenConfidentialOperation::EmptyAccount,
&references
)
.is_ok()
);
let invalid = vec![super::SplTokenConfidentialProofReference {
kind: super::SplTokenConfidentialProofKind::ZeroCiphertext,
location: super::SplTokenConfidentialProofLocation::InstructionOffset { offset: 0 },
}];
assert!(
super::validate_confidential_proof_references(
super::SplTokenConfidentialOperation::EmptyAccount,
&invalid
)
.is_err()
);
}
}

View File

@@ -0,0 +1,13 @@
// file: kb_executor_spl_token_2022/src/constants.rs
// version: 5
//! Local constants for the `kb_executor_spl_token_2022` crate. Program identifiers live in `kb_program_ids`.
/// Maximum number of ordered multisig signer occurrences.
pub(crate) const MAX_MULTISIG_SIGNERS: usize = 11;
/// Maximum UI amount string length accepted before transaction assembly.
pub(crate) const MAX_UI_AMOUNT_BYTES: usize = 255;
/// Maximum ordered token accounts accepted by transfer-fee harvest or withdraw builders.
pub(crate) const MAX_TRANSFER_FEE_SOURCE_ACCOUNTS: usize = 255;
/// Canonical tracing target for this crate.
pub(crate) const TRACING_TARGET: &str = "kb_executor_spl_token_2022";

View File

@@ -0,0 +1,332 @@
// file: kb_executor_spl_token_2022/src/executor.rs
// version: 19
//! Exact Token-2022 capability dispatch and typed plan construction.
/// Token-2022 executor implementation.
#[derive(Clone, Debug, Default)]
pub struct SplToken2022Executor;
impl crate::SplToken2022Executor {
fn exact_capability(
&self,
program_id: &kb_model::ProgramId,
operation_code: &str,
) -> kb_execution_api::ExecutionCapability {
if program_id.0 != kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID {
return kb_execution_api::ExecutionCapability::unsupported(
"execution_spl_token_2022_program_not_owned",
format!("program {} is not owned by kb_executor_spl_token_2022", program_id.0),
);
}
if crate::SUPPORTED_OPERATION_CODES.contains(&operation_code) {
return kb_execution_api::ExecutionCapability::supported(operation_code);
}
if operation_code == crate::BATCH_OPERATION {
return kb_execution_api::ExecutionCapability::unsupported(
"execution_spl_token_2022_batch_builder_unavailable",
"Token-2022 Batch is decode-only because spl-token-2022-interface 3.1.1 publishes no official Batch builder",
);
}
if matches!(
operation_code,
"spl_token_2022.initialize_mint_with_rent"
| "spl_token_2022.initialize_account_with_rent"
| "spl_token_2022.initialize_multisig_with_rent"
| "spl_token_2022.initialize_account2"
) {
return kb_execution_api::ExecutionCapability::unsupported(
"execution_spl_token_2022_historical_variant_decode_only",
format!(
"SPL Token operation {operation_code} is an obsolete historical initialization variant; use the current no-Rent operation"
),
);
}
return kb_execution_api::ExecutionCapability::unsupported(
"execution_spl_token_2022_operation_unsupported",
format!("SPL Token operation {operation_code} is not implemented"),
);
}
}
impl kb_execution_api::TypedInstructionExecutor for crate::SplToken2022Executor {
type Intent = crate::SplToken2022ExecutionIntent;
fn capability(
&self,
program_id: &kb_model::ProgramId,
operation_code: &str,
) -> kb_execution_api::ExecutionCapability {
return self.exact_capability(program_id, operation_code);
}
fn build_prepared_plan(
&self,
intent: &Self::Intent,
) -> kb_core::Result<kb_execution_api::PreparedExecutionPlan> {
let program_id = kb_model::ProgramId(std::string::String::from(
kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID,
));
return match self.exact_capability(&program_id, intent.operation.operation_code()) {
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {
crate::build_prepared_plan(intent)
},
kb_execution_api::ExecutionCapability::Unsupported { reason_code, reason } => {
std::result::Result::Err(kb_core::Error::new(reason_code, reason))
},
};
}
}
impl kb_execution_api::InstructionExecutor for crate::SplToken2022Executor {
fn executor_name(&self) -> &'static str {
return "kb_executor_spl_token_2022";
}
fn executor_version(&self) -> &'static str {
return env!("CARGO_PKG_VERSION");
}
fn program_ids(&self) -> &'static [&'static str] {
return &[kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID];
}
fn supports_request(
&self,
request: &kb_execution_api::ExecutionRequest,
) -> kb_execution_api::ExecutionSupport {
return match self.exact_capability(&request.program_id, &request.operation_code) {
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {
kb_execution_api::ExecutionSupport::Yes
},
kb_execution_api::ExecutionCapability::Unsupported { reason_code: _, reason: _ } => {
kb_execution_api::ExecutionSupport::No
},
};
}
fn build_plan(
&self,
request: &kb_execution_api::ExecutionRequest,
) -> kb_core::Result<kb_execution_api::ExecutionPlan> {
match self.exact_capability(&request.program_id, &request.operation_code) {
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {},
kb_execution_api::ExecutionCapability::Unsupported { reason_code, reason } => {
return std::result::Result::Err(kb_core::Error::new(reason_code, reason));
},
}
let intent =
match serde_json::from_str::<crate::SplToken2022ExecutionIntent>(&request.payload_json)
{
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_token_2022_intent_deserialize_failed",
error.to_string(),
));
},
};
if intent.operation.operation_code() != request.operation_code.as_str() {
return std::result::Result::Err(kb_core::Error::new(
"execution_operation_code_mismatch",
format!(
"request operation {} does not match typed intent operation {}",
request.operation_code,
intent.operation.operation_code()
),
));
}
let prepared =
match kb_execution_api::TypedInstructionExecutor::build_prepared_plan(self, &intent) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let payload_value = match serde_json::to_value(&prepared) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_token_2022_plan_serialize_failed",
error.to_string(),
));
},
};
let payload_json = match kb_execution_api::serialize_payload_json(&payload_value) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(kb_execution_api::ExecutionPlan {
executor_name: std::string::String::from("kb_executor_spl_token_2022"),
instruction_count: prepared.instructions.len(),
payload_json,
});
}
}
#[cfg(test)]
mod tests {
fn request(program_id: &str, operation_code: &str) -> kb_execution_api::ExecutionRequest {
return kb_execution_api::ExecutionRequest {
program_id: kb_model::ProgramId(program_id.to_string()),
operation_code: operation_code.to_string(),
payload_json: std::string::String::from("{}"),
};
}
#[test]
fn exact_capabilities_cover_current_and_recent_operations_only() {
let executor = crate::SplToken2022Executor;
for operation_code in crate::SUPPORTED_OPERATION_CODES {
let request = request(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID, operation_code);
assert_eq!(
kb_execution_api::InstructionExecutor::supports_request(&executor, &request),
kb_execution_api::ExecutionSupport::Yes
);
}
for operation_code in [
"spl_token_2022.initialize_mint_with_rent",
"spl_token_2022.initialize_account_with_rent",
"spl_token_2022.initialize_multisig_with_rent",
"spl_token_2022.initialize_account2",
] {
let capability = kb_execution_api::TypedInstructionExecutor::capability(
&executor,
&kb_model::ProgramId(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.to_string()),
operation_code,
);
match capability {
kb_execution_api::ExecutionCapability::Unsupported { reason_code, reason: _ } => {
assert_eq!(
reason_code,
"execution_spl_token_2022_historical_variant_decode_only"
);
},
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {
panic!("historical variant must be decode-only");
},
}
}
}
#[test]
fn program_dispatch_is_exact() {
let executor = crate::SplToken2022Executor;
let foreign =
request(kb_program_ids::SPL_TOKEN_PROGRAM_ID, crate::TRANSFER_CHECKED_OPERATION);
assert_eq!(
kb_execution_api::InstructionExecutor::supports_request(&executor, &foreign),
kb_execution_api::ExecutionSupport::No
);
}
#[test]
fn machine_readable_matrix_matches_executor_policy() {
let matrix = serde_json::from_str::<serde_json::Value>(include_str!(
"../../docs/SPL_TOKEN_2022_MATRIX.json"
))
.unwrap_or_else(|error| panic!("matrix parsing failed: {error}"));
let instructions = matrix["instructions"]
.as_array()
.unwrap_or_else(|| panic!("matrix instructions must be an array"));
let extension_types = matrix["extensionTypes"]
.as_array()
.unwrap_or_else(|| panic!("matrix extensionTypes must be an array"));
let matrix_names = instructions
.iter()
.chain(extension_types.iter())
.filter_map(|instruction| return instruction["name"].as_str())
.collect::<std::collections::BTreeSet<_>>();
assert_eq!(instructions.len(), 48);
for operation_code in crate::SUPPORTED_OPERATION_CODES {
let name = operation_code
.strip_prefix("spl_token_2022.")
.unwrap_or_else(|| panic!("invalid operation code {operation_code}"));
let matrix_name = match name {
"initialize_interest_bearing_mint" | "update_interest_bearing_rate" => {
"interest_bearing_mint_extension"
},
"initialize_transfer_fee_config"
| "set_transfer_fee"
| "transfer_checked_with_fee"
| "withdraw_withheld_tokens_from_mint"
| "withdraw_withheld_tokens_from_accounts"
| "harvest_withheld_tokens_to_mint" => "transfer_fee_extension",
"initialize_default_account_state" | "update_default_account_state" => {
"default_account_state_extension"
},
"enable_required_transfer_memos" | "disable_required_transfer_memos" => {
"memo_transfer_extension"
},
"enable_cpi_guard" | "disable_cpi_guard" => "cpi_guard_extension",
"initialize_transfer_hook" | "update_transfer_hook" => "transfer_hook_extension",
"initialize_metadata_pointer" | "update_metadata_pointer" => {
"metadata_pointer_extension"
},
"initialize_group_pointer" | "update_group_pointer" => "group_pointer_extension",
"initialize_group_member_pointer" | "update_group_member_pointer" => {
"group_member_pointer_extension"
},
"initialize_token_metadata"
| "update_token_metadata_field"
| "remove_token_metadata_key" => "token_metadata",
"initialize_token_group" | "update_token_group_max_size" => "token_group",
"initialize_token_group_member" => "token_group_member",
"initialize_scaled_ui_amount" | "update_scaled_ui_amount_multiplier" => {
"scaled_ui_amount_extension"
},
"initialize_pausable_config" | "pause" | "resume" => "pausable_extension",
"initialize_permissioned_burn"
| "permissioned_burn"
| "permissioned_burn_checked"
| "permissioned_confidential_burn" => "permissioned_burn_extension",
"initialize_confidential_transfer_mint"
| "update_confidential_transfer_mint"
| "apply_pending_confidential_balance"
| "approve_confidential_transfer_account"
| "deposit_confidential_tokens"
| "enable_confidential_credits"
| "disable_confidential_credits"
| "enable_non_confidential_credits"
| "disable_non_confidential_credits"
| "configure_confidential_transfer_account"
| "configure_confidential_transfer_account_with_registry"
| "empty_confidential_transfer_account"
| "withdraw_confidential_tokens"
| "transfer_confidential_tokens"
| "transfer_confidential_tokens_with_fee" => "confidential_transfer_extension",
"initialize_confidential_transfer_fee_config"
| "enable_confidential_transfer_fee_harvest"
| "disable_confidential_transfer_fee_harvest"
| "harvest_confidential_withheld_tokens_to_mint"
| "withdraw_confidential_withheld_tokens_from_mint"
| "withdraw_confidential_withheld_tokens_from_accounts" => {
"confidential_transfer_fee_extension"
},
"initialize_confidential_mint_burn_mint"
| "rotate_confidential_supply_elgamal_pubkey"
| "update_confidential_decryptable_supply"
| "apply_pending_confidential_burn"
| "confidential_mint"
| "confidential_burn" => "confidential_mint_burn_extension",
_ => name,
};
assert!(
matrix_names.contains(matrix_name),
"matrix is missing supported operation {name}"
);
}
assert!(matrix_names.contains("batch"));
let batch = kb_execution_api::TypedInstructionExecutor::capability(
&crate::SplToken2022Executor,
&kb_model::ProgramId(kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID.to_string()),
crate::BATCH_OPERATION,
);
match batch {
kb_execution_api::ExecutionCapability::Unsupported { reason_code, reason: _ } => {
assert_eq!(reason_code, "execution_spl_token_2022_batch_builder_unavailable");
},
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {
panic!("Batch must remain decode-only");
},
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
// file: kb_executor_spl_token_2022/src/lib.rs
// version: 27
//! Executor crate for `spl_token_2022`.
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
mod builder;
mod confidential;
mod constants;
mod executor;
mod intent;
/// Crate-root access to `build_prepared_plan` from `builder`.
pub(crate) use crate::builder::build_prepared_plan;
/// Maximum number of ordered multisig signer occurrences.
pub(crate) use crate::constants::MAX_MULTISIG_SIGNERS;
/// Maximum ordered token accounts accepted by transfer-fee harvest or withdraw builders.
pub(crate) use crate::constants::MAX_TRANSFER_FEE_SOURCE_ACCOUNTS;
/// Maximum UI amount string length accepted before transaction assembly.
pub(crate) use crate::constants::MAX_UI_AMOUNT_BYTES;
/// Canonical tracing target for this crate.
pub(crate) use crate::constants::TRACING_TARGET;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::CONFIDENTIAL_TRANSFER_EXTERNAL_TAG;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::CONFIDENTIAL_TRANSFER_WITH_FEE_INSTRUCTION_DATA_BYTES;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::CONFIDENTIAL_TRANSFER_WITH_FEE_PAYLOAD_BYTES;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::CONFIDENTIAL_TRANSFER_WITH_FEE_SUBTAG;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::DECRYPTABLE_BALANCE_BYTES;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::ELGAMAL_CIPHERTEXT_BYTES;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::ELGAMAL_PUBKEY_BYTES;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::MAX_CONFIDENTIAL_PROOF_REFERENCES;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenConfidentialExecutorSupport;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenConfidentialMintBurnOperation;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenConfidentialOperation;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenConfidentialProofKind;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenConfidentialProofLocation;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenConfidentialProofReference;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenDecryptableBalance;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenElGamalCiphertext;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::SplTokenElGamalPubkey;
/// Exposes the audited Confidential Transfer operation inventory.
pub use crate::confidential::validate_confidential_proof_references;
/// Exposes the typed SPL Token executor.
pub use crate::executor::SplToken2022Executor;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::AMOUNT_TO_UI_AMOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::APPLY_PENDING_CONFIDENTIAL_BALANCE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::APPLY_PENDING_CONFIDENTIAL_BURN_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::APPROVE_CHECKED_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::APPROVE_CONFIDENTIAL_TRANSFER_ACCOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::APPROVE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::BATCH_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::BURN_CHECKED_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::BURN_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::CLOSE_ACCOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::CONFIDENTIAL_BURN_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::CONFIDENTIAL_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::CONFIGURE_CONFIDENTIAL_TRANSFER_ACCOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::CONFIGURE_CONFIDENTIAL_TRANSFER_ACCOUNT_WITH_REGISTRY_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::DEPOSIT_CONFIDENTIAL_TOKENS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::DISABLE_CONFIDENTIAL_CREDITS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::DISABLE_CONFIDENTIAL_TRANSFER_FEE_HARVEST_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::DISABLE_CPI_GUARD_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::DISABLE_NON_CONFIDENTIAL_CREDITS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::DISABLE_REQUIRED_TRANSFER_MEMOS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::EMPTY_CONFIDENTIAL_TRANSFER_ACCOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::ENABLE_CONFIDENTIAL_CREDITS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::ENABLE_CONFIDENTIAL_TRANSFER_FEE_HARVEST_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::ENABLE_CPI_GUARD_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::ENABLE_NON_CONFIDENTIAL_CREDITS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::ENABLE_REQUIRED_TRANSFER_MEMOS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::FREEZE_ACCOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::GET_ACCOUNT_DATA_SIZE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::HARVEST_CONFIDENTIAL_WITHHELD_TOKENS_TO_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::HARVEST_WITHHELD_TOKENS_TO_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_ACCOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_CONFIDENTIAL_MINT_BURN_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_CONFIDENTIAL_TRANSFER_FEE_CONFIG_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_CONFIDENTIAL_TRANSFER_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_DEFAULT_ACCOUNT_STATE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_GROUP_MEMBER_POINTER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_GROUP_POINTER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_IMMUTABLE_OWNER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_INTEREST_BEARING_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_METADATA_POINTER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_MULTISIG_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_NON_TRANSFERABLE_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_PAUSABLE_CONFIG_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_PERMANENT_DELEGATE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_PERMISSIONED_BURN_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_SCALED_UI_AMOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_TOKEN_GROUP_MEMBER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_TOKEN_GROUP_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_TOKEN_METADATA_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_TRANSFER_FEE_CONFIG_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::INITIALIZE_TRANSFER_HOOK_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::MINT_TO_CHECKED_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::MINT_TO_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::PAUSE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::PERMISSIONED_BURN_CHECKED_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::PERMISSIONED_BURN_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::PERMISSIONED_CONFIDENTIAL_BURN_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::REALLOCATE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::REMOVE_TOKEN_METADATA_KEY_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::RESUME_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::REVOKE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::ROTATE_CONFIDENTIAL_SUPPLY_ELGAMAL_PUBKEY_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::SET_AUTHORITY_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::SET_TRANSFER_FEE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::SUPPORTED_OPERATION_CODES;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::SYNC_NATIVE_OPERATION;
/// Exposes the complete typed execution intent.
pub use crate::intent::SplToken2022ExecutionIntent;
/// Exposes the top-level operation contract.
pub use crate::intent::SplToken2022Operation;
/// Exposes the exact raw amount string contract.
pub use crate::intent::SplTokenAmount;
/// Exposes the typed authority contract.
pub use crate::intent::SplTokenAuthority;
/// Exposes the typed authority-kind contract.
pub use crate::intent::SplTokenAuthorityType;
/// Exposes the typed default-account-state contract.
pub use crate::intent::SplTokenDefaultAccountState;
/// Exposes the typed token-metadata field contract.
pub use crate::intent::SplTokenMetadataField;
/// Exposes the bounded scaled-UI multiplier contract.
pub use crate::intent::SplTokenMultiplier;
/// Exposes the non-batch operation contract.
pub use crate::intent::SplTokenSingleOperation;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::THAW_ACCOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::TRANSFER_CHECKED_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::TRANSFER_CHECKED_WITH_FEE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::TRANSFER_CONFIDENTIAL_TOKENS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::TRANSFER_CONFIDENTIAL_TOKENS_WITH_FEE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::TRANSFER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UI_AMOUNT_TO_AMOUNT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UNWRAP_LAMPORTS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_CONFIDENTIAL_DECRYPTABLE_SUPPLY_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_CONFIDENTIAL_TRANSFER_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_DEFAULT_ACCOUNT_STATE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_GROUP_MEMBER_POINTER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_GROUP_POINTER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_INTEREST_BEARING_RATE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_METADATA_POINTER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_SCALED_UI_AMOUNT_MULTIPLIER_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_TOKEN_GROUP_MAX_SIZE_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_TOKEN_METADATA_FIELD_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::UPDATE_TRANSFER_HOOK_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::WITHDRAW_CONFIDENTIAL_TOKENS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::WITHDRAW_CONFIDENTIAL_WITHHELD_TOKENS_FROM_ACCOUNTS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::WITHDRAW_CONFIDENTIAL_WITHHELD_TOKENS_FROM_MINT_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::WITHDRAW_EXCESS_LAMPORTS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::WITHDRAW_WITHHELD_TOKENS_FROM_ACCOUNTS_OPERATION;
/// Exposes stable operation codes for generic executor dispatch.
pub use crate::intent::WITHDRAW_WITHHELD_TOKENS_FROM_MINT_OPERATION;