spl_token_confidential_transfer_proof_extraction/
mint.rsuse {
crate::{encryption::PodMintAmountCiphertext, errors::TokenProofExtractionError},
solana_zk_sdk::{
encryption::pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey},
zk_elgamal_proof_program::proof_data::{
BatchedGroupedCiphertext3HandlesValidityProofContext, BatchedRangeProofContext,
CiphertextCommitmentEqualityProofContext,
},
},
};
pub struct MintPubkeys {
pub destination: PodElGamalPubkey,
pub auditor: PodElGamalPubkey,
pub supply: PodElGamalPubkey,
}
pub struct MintProofContext {
pub mint_amount_ciphertext_lo: PodMintAmountCiphertext,
pub mint_amount_ciphertext_hi: PodMintAmountCiphertext,
pub mint_pubkeys: MintPubkeys,
pub new_supply_ciphertext: PodElGamalCiphertext,
}
impl MintProofContext {
pub fn verify_and_extract(
equality_proof_context: &CiphertextCommitmentEqualityProofContext,
ciphertext_validity_proof_context: &BatchedGroupedCiphertext3HandlesValidityProofContext,
range_proof_context: &BatchedRangeProofContext,
) -> Result<Self, TokenProofExtractionError> {
let CiphertextCommitmentEqualityProofContext {
pubkey: supply_elgamal_pubkey_from_equality_proof,
ciphertext: new_supply_ciphertext,
commitment: new_supply_commitment,
} = equality_proof_context;
let BatchedGroupedCiphertext3HandlesValidityProofContext {
first_pubkey: destination_elgamal_pubkey,
second_pubkey: auditor_elgamal_pubkey,
third_pubkey: supply_elgamal_pubkey_from_ciphertext_validity_proof,
grouped_ciphertext_lo: mint_amount_ciphertext_lo,
grouped_ciphertext_hi: mint_amount_ciphertext_hi,
} = ciphertext_validity_proof_context;
let BatchedRangeProofContext {
commitments: range_proof_commitments,
bit_lengths: range_proof_bit_lengths,
} = range_proof_context;
if supply_elgamal_pubkey_from_equality_proof
!= supply_elgamal_pubkey_from_ciphertext_validity_proof
{
return Err(TokenProofExtractionError::ElGamalPubkeyMismatch);
}
let mint_amount_commitment_lo = mint_amount_ciphertext_lo.extract_commitment();
let mint_amount_commitment_hi = mint_amount_ciphertext_hi.extract_commitment();
let expected_commitments = [
*new_supply_commitment,
mint_amount_commitment_lo,
mint_amount_commitment_hi,
];
if !range_proof_commitments
.iter()
.zip(expected_commitments.iter())
.all(|(proof_commitment, expected_commitment)| proof_commitment == expected_commitment)
{
return Err(TokenProofExtractionError::PedersenCommitmentMismatch);
}
const NEW_SUPPLY_BIT_LENGTH: u8 = 64;
const MINT_AMOUNT_LO_BIT_LENGTH: u8 = 16;
const MINT_AMOUNT_HI_BIT_LENGTH: u8 = 32;
const PADDING_BIT_LENGTH: u8 = 16;
let expected_bit_lengths = [
NEW_SUPPLY_BIT_LENGTH,
MINT_AMOUNT_LO_BIT_LENGTH,
MINT_AMOUNT_HI_BIT_LENGTH,
PADDING_BIT_LENGTH,
]
.iter();
if !range_proof_bit_lengths
.iter()
.zip(expected_bit_lengths)
.all(|(proof_len, expected_len)| proof_len == expected_len)
{
return Err(TokenProofExtractionError::RangeProofLengthMismatch);
}
let mint_pubkeys = MintPubkeys {
destination: *destination_elgamal_pubkey,
auditor: *auditor_elgamal_pubkey,
supply: *supply_elgamal_pubkey_from_equality_proof,
};
Ok(MintProofContext {
mint_amount_ciphertext_lo: PodMintAmountCiphertext(*mint_amount_ciphertext_lo),
mint_amount_ciphertext_hi: PodMintAmountCiphertext(*mint_amount_ciphertext_hi),
mint_pubkeys,
new_supply_ciphertext: *new_supply_ciphertext,
})
}
}