Guía del Emisor de Transferencias Confidenciales

Emisión de Tokens de Transferencia Confidencial en Solana

Esta guía está dirigida a emisores: equipos que crean y operan un mint de Token-2022 que utiliza la extensión de Transferencia Confidencial. Cubre las decisiones que tomas en el momento de la creación del mint y las operaciones que realizas durante la vida del mint. Para el flujo del titular (depósito, aplicación, transferencia, retiro), consulta las páginas paso a paso, y para dar soporte a estos tokens en un producto, consulta la Guía de Integración.

Las transferencias confidenciales mantienen los montos de transferencia y los saldos de las cuentas cifrados, mientras que las direcciones de las cuentas, el mint y los propietarios permanecen públicos. Se basan en el Programa de Pruebas ZK ElGamal para la verificación de pruebas en cadena, por lo que el mint es utilizable en clústeres donde ese programa está habilitado.

Disponibilidad

Las transferencias confidenciales requieren el Token-2022 program@v11.0.0 o posterior. Están disponibles en devnet hoy y está previsto habilitarlas en mainnet en junio de 2026. El Token Extension Program se despliega de forma independiente en cada clúster, así que confirma el despliegue en el clúster que uses.

Decisiones que tomas en la creación

La extensión de Transferencia Confidencial debe inicializarse antes de que se inicialice el mint y no puede añadirse posteriormente. En el momento de la creación decides:

  • Política de aprobación: si las cuentas pueden optar por las transferencias confidenciales de forma sin permisos (auto) o deben ser aprobadas por la autoridad de transferencia confidencial del mint (manual).
  • Auditor: si se establece una clave pública ElGamal de auditor global para que una parte designada pueda descifrar todos los montos de transferencia del mint. Opcional, y puede modificarse posteriormente.
  • Extensiones complementarias opcionales: comisiones de transferencia confidencial (combinadas con la extensión de comisión de transferencia) y emisión/quema confidencial, ambas descritas a continuación. Estas también deben inicializarse en el momento de la creación.

Crear una acuñación confidencial

La CLI establece la política de aprobación con --enable-confidential-transfers auto o manual; auto permite que cualquier titular configure su propia cuenta, mientras que manual condiciones eso a la aprobación de la autoridad de transferencia confidencial (que por defecto es la autoridad de acuñación). Las rutas del cliente reciben la misma configuración a través de los parámetros ConfidentialTransferMint: una autoridad, el indicador de aprobación automática y una clave de auditor opcional. Tanto la política de aprobación como el auditor pueden cambiarse posteriormente (consulte Configurar un auditor); solo la presencia de la propia extensión queda fijada en el momento de la creación.

$ spl-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb create-token --enable-confidential-transfers auto

Configurar un auditor

Un auditor global es una clave pública ElGamal almacenada en la acuñación. Cuando se establece, cada transferencia confidencial cifra adicionalmente su importe con esta clave, de modo que quien posea la clave secreta correspondiente puede descifrar todos los importes de transferencia de la acuñación. Así es como las transferencias confidenciales siguen siendo compatibles con los requisitos de auditoría y cumplimiento: el público no ve nada, el auditor lo ve todo.

La autoridad de transferencia confidencial puede establecer, rotar o eliminar el auditor en cualquier momento. La misma operación también actualiza la política de aprobación. En la CLI, la clave del auditor es una codificación en base64 de una clave pública ElGamal; pase --auditor-pubkey none para eliminarla e --approve-policy auto|manual para cambiar la política.

La rotación solo afecta a las transferencias futuras. Los importes de las transacciones ya registradas en la cadena permanecen cifrados con la clave de auditor que estaba activa en el momento de su ejecución, por lo que conserve las claves de auditor antiguas si necesita descifrar la actividad histórica.

$ spl-token update-confidential-transfer-settings <MINT_PUBKEY> --auditor-pubkey <AUDITOR_ELGAMAL_PUBKEY>

La clave secreta del auditor puede descifrar todos los importes de transferencia de la acuñación. Custódiela con el mismo rigor que una clave de firma y planifique su rotación. Establecer el auditor en None deshabilita la visibilidad de los importes para todos excepto para los propios titulares de las cuentas.

Aprobar cuentas (política manual)

Con una política de aprobación manual, una cuenta configurada para transferencias confidenciales no puede realizar transacciones de forma confidencial hasta que la autoridad de transferencias confidenciales la apruebe. Esto le otorga a los emisores un control de acceso para participantes en lista de permitidos o verificados mediante KYC. La CLI no expone un comando de aprobación, por lo que la aprobación se realiza a través de un cliente.

token
.confidential_transfer_approve_account(
&token_account,
&authority,
&[&authority_keypair],
)
.await?;

Comisiones de transferencia confidencial

Si tu mint cobra una comisión por transferencia y las transferencias son confidenciales, la comisión también debe retenerse de forma confidencial. La extensión ConfidentialTransferFeeConfig gestiona esto, y se inicializa en el momento de creación del mint junto con las extensiones de comisión por transferencia y de transferencia confidencial.

Las comisiones retenidas se acumulan cifradas en las cuentas de los destinatarios, se transfieren al mint y luego son retiradas por la autoridad de retiro de comisiones retenidas. Todos los importes de las comisiones permanecen cifrados en todo momento. Nada de esto está expuesto a través de la CLI. La clave secreta ElGamal de la autoridad de retiro de comisiones retenidas puede descifrar los importes de las comisiones retenidas, lo cual, combinado con los parámetros públicos de comisiones, puede revelar información sobre los importes de las transferencias, por lo que debes tratar esa clave como información sensible.

Inicializar la configuración de comisiones

Incluye esto junto con ConfidentialTransferMint y la configuración de comisiones por transferencia en la misma creación del mint.

use spl_token_client::token::ExtensionInitializationParams;
ExtensionInitializationParams::ConfidentialTransferFeeConfig {
authority: Some(authority.pubkey().into()),
withdraw_withheld_authority_elgamal_pubkey: withdraw_withheld_elgamal_pubkey,
};

Cosechar y retirar comisiones retenidas

La cosecha mueve las comisiones retenidas cifradas desde las cuentas hacia el mint; el retiro las saca del mint hacia una cuenta elegida. Intervienen dos autoridades, y cualquiera de ellas puede ser diferente a la autoridad del mint:

  • La autoridad de comisiones de transferencia confidencial (el authority configurado en ConfidentialTransferFeeConfig) habilita o deshabilita la cosecha.
  • La autoridad de retiro de comisiones retenidas (de la TransferFeeConfig de la extensión de comisiones por transferencia) retira las comisiones cosechadas fuera del mint.

Los retiros requieren una prueba de igualdad y una prueba de rango, suministradas en línea o verificadas en cuentas de estado de contexto.

// Permissionless: move withheld fees from accounts into the mint.
token
.confidential_transfer_harvest_withheld_tokens_to_mint(&[&source_account])
.await?;
// Withdraw withheld fees from the mint (requires the withdraw withheld authority).
token
.confidential_transfer_withdraw_withheld_tokens_from_mint(
&destination_account,
&withdraw_withheld_authority,
None, // proof context state account, supplied inline if None
None, // withheld tokens info, fetched if None
&withdraw_withheld_elgamal_keypair,
&destination_elgamal_pubkey,
&new_decryptable_available_balance,
&[&withdraw_withheld_authority_keypair],
)
.await?;

En el cliente JS, retirar las comisiones recolectadas del mint (getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction) también requiere una prueba de igualdad y una prueba de rango verificadas en cuentas de estado de contexto, por lo que sigue el mismo patrón de cuenta de prueba que una transferencia confidencial.

Acuñación y quema confidencial

La extensión ConfidentialMintBurn permite a la autoridad del mint emitir y quemar suministro directamente contra saldos confidenciales, manteniendo el suministro total cifrado. Un mint con esta extensión deshabilita la ruta pública de depósito y retiro, ya que los tokens solo existen de forma confidencial. Consulta la documentación del protocolo para el modelo completo.

La acuñación/quema confidencial es más sencilla a través del crate de Rust spl-token-client, que genera las pruebas necesarias y secuencia las transacciones por ti. El cliente JS @solana-program/token-2022 incluye los constructores de instrucciones de bajo nivel (getConfidentialMintInstruction, getConfidentialBurnInstruction y similares), pero no un helper de alto nivel que construya las pruebas, y no hay comandos CLI, por lo que los ejemplos a continuación son solo en Rust.

Inicializa la extensión al crear el mint, luego acuña, quema y reconcilia el suministro con el tiempo. La acuñación emite una cantidad cifrada en el saldo confidencial de un destinatario; la quema elimina una cantidad cifrada en una quema pendiente que posteriormente se incorpora al suministro. Ambas generan pruebas como una transferencia confidencial.

confidential-mint-burn.rs
use spl_token_client::token::ExtensionInitializationParams;
// 1. Initialize at creation (alongside ConfidentialTransferMint).
ExtensionInitializationParams::ConfidentialMintBurn {
supply_elgamal_pubkey, // encrypts the confidential supply
decryptable_supply, // AES ciphertext of the initial supply (zero)
};
// 2. Mint an encrypted amount into a recipient's confidential balance.
token
.confidential_transfer_mint(
&mint_authority,
&destination_account,
None, // equality proof account
None, // ciphertext validity proof account
None, // range proof account
mint_amount,
&supply_elgamal_keypair,
&destination_elgamal_pubkey,
auditor_elgamal_pubkey, // Option
&supply_aes_key,
None, // supply account info, fetched if None
&[&mint_authority_keypair],
)
.await?;
// 3. Burn an encrypted amount from a holder's confidential balance into the
// mint's pending burn. Generates proofs like a confidential transfer.
token
.confidential_transfer_burn(
&owner,
&source_account,
None, // equality proof account
None, // ciphertext validity proof account
None, // range proof account
burn_amount,
&source_elgamal_keypair,
&supply_elgamal_pubkey,
auditor_elgamal_pubkey, // Option
&source_aes_key,
None, // burn account info, fetched if None
&[&owner_keypair],
)
.await?;
// 4. Fold the accumulated pending burn into the confidential supply.
token
.confidential_transfer_apply_pending_burn(&mint_authority, &[&mint_authority_keypair])
.await?;

Rota la clave de cifrado del suministro con confidential_transfer_rotate_supply_elgamal_pubkey (la quema pendiente debe ser cero primero), y actualiza el texto cifrado del suministro legible con confidential_transfer_update_decrypt_supply.

Consideraciones operativas y de cumplimiento

  • Custodia de la clave del auditor. Si configuras un auditor, la clave secreta del auditor es una clave de descifrado de alto valor. Almacénala y rótala con cuidado, y decide quién dentro de tu organización (o qué regulador) la custodia.
  • Postura de cumplimiento. El análisis de direcciones y el análisis del grafo de contrapartes siguen funcionando porque las direcciones son públicas. El monitoreo basado en montos depende de la clave del auditor o de la divulgación selectiva por parte de los titulares de cuentas. Define tu enfoque antes del lanzamiento.
  • Incorporación de titulares. Configurar una cuenta confidencial requiere la firma del propietario. Para aprovisionar cuentas de usuarios de forma fluida, haz que registren una clave ElGamal una vez y utilicen la ruta del registro, descrita en la Guía de integración.
  • Número de transacciones. Una transferencia confidencial abarca actualmente varias transacciones dependientes porque las pruebas superan el límite de tamaño de transacción actual. El formato de transacción v1 (que llega con Agave v4.2) eleva ese límite y se espera que permita una única transacción en cadena.

Is this page helpful?