기밀 전송 발행자 가이드

Solana에서 기밀 전송 토큰 발행하기

이 가이드는 발행자, 즉 Confidential Transfer 확장을 사용하는 Token-2022 민트를 생성하고 운영하는 팀을 위한 문서입니다. 민트 생성 시 결정해야 할 사항과 민트 운영 기간 동안 수행하는 작업을 다룹니다. 보유자 측 흐름(입금, 적용, 전송, 출금)은 단계별 페이지를 참조하고, 제품에서 이 토큰을 지원하는 방법은 통합 가이드를 참조하세요.

기밀 전송은 계정 주소, 민트, 소유자는 공개적으로 유지하면서 전송 금액과 계정 잔액을 암호화된 상태로 유지합니다. 온체인 증명 검증을 위해 ZK ElGamal Proof Program에 의존하므로, 해당 프로그램이 활성화된 클러스터에서만 민트를 사용할 수 있습니다.

가용성

기밀 전송을 사용하려면 Token-2022 program@v11.0.0 이상이 필요합니다. 현재 devnet에서 사용 가능하며, 2026년 6월에 mainnet에서 활성화될 예정입니다. Token Extensions Program은 각 클러스터에 별도로 배포되므로, 대상 클러스터에서의 배포 여부를 확인하세요.

생성 시 결정 사항

Confidential Transfer 확장은 민트가 초기화되기 전에 초기화해야 하며, 이후에는 추가할 수 없습니다. 생성 시 다음 사항을 결정합니다:

  • 승인 정책: 계정이 권한 없이 기밀 전송을 선택할 수 있는지(auto), 아니면 민트의 기밀 전송 권한자에 의해 승인을 받아야 하는지(manual).
  • 감사자: 지정된 당사자가 민트의 모든 전송 금액을 복호화할 수 있도록 전역 감사자 ElGamal 공개 키를 설정할지 여부. 선택 사항이며 나중에 변경할 수 있습니다.
  • 선택적 보조 확장: 기밀 전송 수수료(전송 수수료 확장과 연동)와 기밀 민팅/소각이 있으며, 두 가지 모두 아래에서 다룹니다. 이 확장들도 생성 시 초기화해야 합니다.

기밀 민트 생성

CLI는 --enable-confidential-transfers auto 또는 manual로 승인 정책을 설정합니다. auto는 모든 보유자가 자신의 계정을 직접 구성할 수 있게 하며, manual는 기밀 전송 권한(기본값은 민트 권한)의 승인을 통해 이를 제한합니다. 클라이언트 경로는 ConfidentialTransferMint 매개변수를 통해 동일한 설정을 받습니다: 권한, 자동 승인 플래그, 그리고 선택적 감사자 키. 승인 정책과 감사자는 모두 나중에 변경할 수 있습니다 (감사자 구성 참고). 확장 자체의 존재 여부만 생성 시 고정됩니다.

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

감사자 구성

글로벌 감사자는 민트에 저장된 ElGamal 공개 키입니다. 설정되면 모든 기밀 전송은 이 키로 금액을 추가로 암호화하므로, 해당 비밀 키를 보유한 사람은 민트의 모든 전송 금액을 복호화할 수 있습니다. 이것이 기밀 전송이 감사 및 컴플라이언스 요구 사항과 호환되는 방식입니다: 공개적으로는 아무것도 보이지 않고, 감사자는 모든 것을 볼 수 있습니다.

기밀 전송 권한은 언제든지 감사자를 설정, 교체 또는 제거할 수 있습니다. 동일한 작업으로 승인 정책도 업데이트됩니다. CLI에서 감사자 키는 ElGamal 공개 키의 base64 인코딩입니다. 제거하려면 --auditor-pubkey none를 전달하고, 정책을 변경하려면 --approve-policy auto|manual를 전달하십시오.

교체는 이후 전송에만 영향을 미칩니다. 이미 온체인에 기록된 트랜잭션의 금액은 실행 당시 활성화된 감사자 키로 암호화된 상태로 유지되므로, 과거 활동을 복호화해야 하는 경우 이전 감사자 키를 보관하십시오.

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

감사자 비밀 키는 민트의 모든 전송 금액을 복호화할 수 있습니다. 서명 키와 동일한 수준의 엄격함으로 보관하고, 교체 계획을 수립하십시오. 감사자를 None로 설정하면 계정 소유자 본인을 제외한 모든 사람에 대해 금액 가시성이 비활성화됩니다.

계정 승인 (수동 정책)

수동 승인 정책을 사용하면, 기밀 전송용으로 구성된 계정은 기밀 전송 권한이 승인하기 전까지 기밀 거래를 수행할 수 없습니다. 이를 통해 발행자는 허용 목록에 등록되거나 KYC를 완료한 참여자에 대한 게이트를 설정할 수 있습니다. CLI에는 승인 명령이 노출되지 않으므로, 승인은 클라이언트를 통해 수행됩니다.

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

기밀 전송 수수료

민트에 전송 수수료가 부과되고 전송이 기밀인 경우, 수수료도 기밀로 원천 징수되어야 합니다. ConfidentialTransferFeeConfig 확장이 이를 처리하며, 전송 수수료 및 기밀 전송 확장과 함께 민트 생성 시 초기화됩니다.

원천 징수된 수수료는 수신자 계정에 암호화된 상태로 누적되고, 민트로 수집된 후 원천 징수 권한자에 의해 출금됩니다. 모든 수수료 금액은 전 과정에서 암호화된 상태를 유지합니다. 이 기능은 CLI를 통해 노출되지 않습니다. 원천 징수 권한자의 ElGamal 비밀 키는 원천 징수된 수수료 금액을 복호화할 수 있으며, 이를 공개 수수료 매개변수와 결합하면 전송 금액에 관한 정보가 노출될 수 있으므로 해당 키를 민감한 정보로 취급하십시오.

수수료 설정 초기화

이 설정을 ConfidentialTransferMint 및 전송 수수료 설정과 함께 동일한 민트 생성 과정에 포함하십시오.

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

원천 징수 수수료 수집 및 출금

수집은 계정에서 민트로 암호화된 원천 징수 수수료를 이동시키고, 출금은 민트에서 지정된 계정으로 수수료를 이동시킵니다. 두 가지 권한이 관여하며, 각각 민트 권한과 다를 수 있습니다:

  • 기밀 전송 수수료 권한 (ConfidentialTransferFeeConfig에 설정된 authority)은 수집을 활성화하거나 비활성화합니다.
  • 원천 징수 권한 (전송 수수료 확장의 TransferFeeConfig)은 민트에서 수집된 수수료를 출금합니다.

출금에는 동등성 증명과 범위 증명이 필요하며, 인라인으로 제공하거나 컨텍스트 상태 계정에 검증하여 사용할 수 있습니다.

// 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?;

JS 클라이언트에서 민트로부터 수확된 수수료를 출금하려면 (getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction) 컨텍스트 상태 계정에 검증된 동등성 증명과 범위 증명이 추가로 필요하므로, 기밀 전송과 동일한 증명 계정 패턴을 따릅니다.

기밀 민트 및 소각

ConfidentialMintBurn 익스텐션은 민트 권한자가 기밀 잔액을 기준으로 직접 공급량을 발행하고 소각할 수 있도록 하여 총 공급량을 암호화된 상태로 유지합니다. 이 익스텐션을 사용하는 민트는 토큰이 항상 기밀 상태로만 존재하기 때문에 공개 입금 및 출금 경로가 비활성화됩니다. 전체 모델에 대한 자세한 내용은 프로토콜 문서를 참조하세요.

기밀 민트/소각은 Rust spl-token-client를 통해 가장 쉽게 처리할 수 있으며, 필요한 증명을 생성하고 트랜잭션 순서를 자동으로 처리합니다. @solana-program/token-2022 JS 클라이언트는 저수준 명령 빌더 (getConfidentialMintInstruction, getConfidentialBurnInstruction 등)를 제공하지만 증명을 빌드하는 고수준 헬퍼는 없으며, CLI 명령도 지원하지 않습니다. 따라서 아래 예제는 Rust 전용입니다.

민트 생성 시 익스텐션을 초기화한 후, 시간이 지남에 따라 민트, 소각, 공급량 조정을 수행합니다. 민팅은 암호화된 금액을 수신자의 기밀 잔액에 발행하고, 소각은 암호화된 금액을 나중에 공급량에 반영되는 보류 중인 소각 항목으로 제거합니다. 두 작업 모두 기밀 전송과 마찬가지로 증명을 생성합니다.

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?;

confidential_transfer_rotate_supply_elgamal_pubkey를 사용하여 공급량 암호화 키를 교체하고 (보류 중인 소각이 먼저 0이어야 함), confidential_transfer_update_decrypt_supply로 읽기 가능한 공급량 암호문을 갱신합니다.

운영 및 컴플라이언스 고려사항

  • 감사자 키 관리. 감사자를 설정한 경우, 감사자 비밀 키는 매우 중요한 복호화 키입니다. 신중하게 보관하고 교체하며, 조직 내에서 누가(또는 어떤 규제 기관이) 이를 보유할지 결정하세요.
  • 컴플라이언스 방침. 주소가 공개 상태로 유지되므로 주소 스크리닝 및 거래 상대방 그래프 분석은 계속 작동합니다. 금액 기반 모니터링은 감사자 키 또는 계정 소유자의 선택적 공개에 의존합니다. 출시 전에 접근 방식을 결정하세요.
  • 보유자 온보딩. 기밀 계정을 구성하려면 소유자의 서명이 필요합니다. 사용자 계정을 원활하게 프로비저닝하려면, 사용자가 ElGamal 키를 한 번 등록하고 레지스트리 경로를 사용하도록 하세요. 자세한 내용은 통합 가이드를 참조하세요.
  • 트랜잭션 수. 현재 기밀 전송은 증명이 현재의 트랜잭션 크기 제한을 초과하기 때문에 몇 개의 종속 트랜잭션에 걸쳐 처리됩니다. 트랜잭션 형식 v1(Agave v4.2와 함께 출시 예정)은 해당 제한을 상향하여 단일 온체인 트랜잭션을 가능하게 할 것으로 기대됩니다.

Is this page helpful?