5959 encryption:: {
6060 auth_encryption:: { AeCiphertext , AeKey } ,
6161 elgamal:: { ElGamalCiphertext , ElGamalKeypair , ElGamalPubkey , ElGamalSecretKey } ,
62- pod:: elgamal:: PodElGamalPubkey ,
62+ pod:: { auth_encryption :: PodAeCiphertext , elgamal:: PodElGamalPubkey } ,
6363 } ,
6464 zk_elgamal_proof_program:: {
6565 self ,
@@ -3598,23 +3598,46 @@ where
35983598 pub async fn confidential_supply (
35993599 & self ,
36003600 supply_elgamal_keypair : & ElGamalKeypair ,
3601+ supply_aes_key : & AeKey ,
36013602 ) -> Result < u64 , TokenError > {
36023603 let mint = self . get_mint_info ( ) . await ?;
36033604 let confidential_mint_burn_ext = mint. get_extension :: < ConfidentialMintBurn > ( ) ?;
36043605
3605- // Currently only correctly displays supplies until u32::MAX,
3606- // the supply ciphertext will still be correct after, but it
3607- // can't be decrypted here until a corresponding decryption
3608- // method is added to the solana-zk-token-sdk
3609- Ok ( supply_elgamal_keypair
3606+ let current_decyptable_supply =
3607+ if confidential_mint_burn_ext. decryptable_supply != PodAeCiphertext :: default ( ) {
3608+ // decrypt the current supply
3609+ let decryptable_supply: AeCiphertext = confidential_mint_burn_ext
3610+ . decryptable_supply
3611+ . try_into ( )
3612+ . map_err ( |_| TokenError :: AccountDecryption ) ?;
3613+ decryptable_supply
3614+ . decrypt ( supply_aes_key)
3615+ . ok_or ( TokenError :: AccountDecryption ) ?
3616+ } else {
3617+ 0
3618+ } ;
3619+
3620+ // get the difference between the supply ciphertext and the decryptable supply
3621+ // explanation see https://github.com/solana-labs/solana-program-library/pull/6881#issuecomment-2385579058
3622+ let decryptable_supply_ciphertext = supply_elgamal_keypair
3623+ . pubkey ( )
3624+ . encrypt ( current_decyptable_supply) ;
3625+ let current_supply: ElGamalCiphertext = confidential_mint_burn_ext
3626+ . confidential_supply
3627+ . try_into ( )
3628+ . map_err ( |_| TokenError :: AccountDecryption ) ?;
3629+ let ct_decryptable_to_current_diff = decryptable_supply_ciphertext - current_supply;
3630+ let decryptable_to_current_diff = supply_elgamal_keypair
36103631 . secret ( )
3611- . decrypt_u32 (
3612- & TryInto :: < ElGamalCiphertext > :: try_into (
3613- confidential_mint_burn_ext. confidential_supply ,
3614- )
3615- . map_err ( |_| TokenError :: Program ( ProgramError :: InvalidAccountData ) ) ?,
3616- )
3617- . unwrap_or_default ( ) )
3632+ . decrypt_u32 ( & ct_decryptable_to_current_diff)
3633+ . ok_or ( TokenError :: AccountDecryption ) ?;
3634+
3635+ // compute the total supply
3636+ current_decyptable_supply
3637+ . checked_sub ( decryptable_to_current_diff)
3638+ . ok_or ( TokenError :: TokenProgramError ( String :: from (
3639+ "Confidential supply underflow" ,
3640+ ) ) )
36183641 }
36193642
36203643 pub async fn supply_elgamal_pubkey ( & self ) -> TokenResult < Option < ElGamalPubkey > > {
@@ -3633,6 +3656,7 @@ where
36333656 & self ,
36343657 authority : & Pubkey ,
36353658 supply_elgamal_keypair : & ElGamalKeypair ,
3659+ supply_aes_key : & AeKey ,
36363660 new_supply_elgamal_keypair : & ElGamalKeypair ,
36373661 signing_keypairs : & S ,
36383662 ) -> TokenResult < T :: Output > {
@@ -3641,7 +3665,7 @@ where
36413665
36423666 let mint = self . get_mint_info ( ) . await ?;
36433667 let extension_state = mint. get_extension :: < ConfidentialMintBurn > ( ) ?;
3644- let current_supply = self . confidential_supply ( supply_elgamal_keypair) . await ?;
3668+ let current_supply = self . confidential_supply ( supply_elgamal_keypair, supply_aes_key ) . await ?;
36453669
36463670 self . process_ixs (
36473671 & confidential_mint_burn:: instruction:: rotate_supply_elgamal (
0 commit comments