기밀 전송 발행자 가이드

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

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

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

생성 시 결정 사항

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

  • 승인 정책: 계정이 권한 없이 기밀 전송을 자유롭게 선택할 수 있는지 (auto), 아니면 민트의 기밀 전송 권한자로부터 승인을 받아야 하는지 (manual).
  • 감사자: 민트의 모든 전송 금액을 지정된 당사자가 복호화할 수 있도록 전역 감사자 ElGamal pubkey를 설정할지 여부. 선택 사항이며 이후에 변경 가능합니다.
  • 선택적 동반 확장: 기밀 전송 수수료(전송 수수료 확장과 연동) 및 기밀 민트/번, 둘 다 아래에서 설명합니다. 이들도 생성 시 초기화되어야 합니다.

기밀 민트 생성

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

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

감사자 구성

전역 감사자는 민트에 저장된 ElGamal pubkey입니다. 설정된 경우, 모든 기밀 전송은 이 키로 전송 금액을 추가로 암호화하므로, 해당 비밀 키를 보유한 사람은 민트의 모든 전송 금액을 복호화할 수 있습니다. 이것이 기밀 전송이 감사 및 규정 준수 요구 사항과 호환되는 방식입니다: 일반 사용자에게는 아무것도 보이지 않고, 감사자에게는 모든 것이 보입니다.

기밀 전송 권한은 언제든지 감사자를 설정, 교체 또는 제거할 수 있습니다. 동일한 작업으로 승인 정책도 함께 업데이트됩니다. 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?