spl_token_confidential_transfer_proof_extraction/
burn.rsuse {
crate::{encryption::PodBurnAmountCiphertext, errors::TokenProofExtractionError},
solana_zk_sdk::{
encryption::pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey},
zk_elgamal_proof_program::proof_data::{
BatchedGroupedCiphertext3HandlesValidityProofContext, BatchedRangeProofContext,
CiphertextCommitmentEqualityProofContext,
},
},
};
pub struct BurnPubkeys {
pub source: PodElGamalPubkey,
pub auditor: PodElGamalPubkey,
pub supply: PodElGamalPubkey,
}
pub struct BurnProofContext {
pub burn_amount_ciphertext_lo: PodBurnAmountCiphertext,
pub burn_amount_ciphertext_hi: PodBurnAmountCiphertext,
pub burn_pubkeys: BurnPubkeys,
pub remaining_balance_ciphertext: PodElGamalCiphertext,
}
impl BurnProofContext {
pub fn verify_and_extract(
equality_proof_context: &CiphertextCommitmentEqualityProofContext,
ciphertext_validity_proof_context: &BatchedGroupedCiphertext3HandlesValidityProofContext,
range_proof_context: &BatchedRangeProofContext,
) -> Result<Self, TokenProofExtractionError> {
let CiphertextCommitmentEqualityProofContext {
pubkey: source_elgamal_pubkey_from_equality_proof,
ciphertext: remaining_balance_ciphertext,
commitment: remaining_balance_commitment,
} = equality_proof_context;
let BatchedGroupedCiphertext3HandlesValidityProofContext {
first_pubkey: source_elgamal_pubkey_from_validity_proof,
second_pubkey: auditor_elgamal_pubkey,
third_pubkey: supply_elgamal_pubkey,
grouped_ciphertext_lo: burn_amount_ciphertext_lo,
grouped_ciphertext_hi: burn_amount_ciphertext_hi,
} = ciphertext_validity_proof_context;
let BatchedRangeProofContext {
commitments: range_proof_commitments,
bit_lengths: range_proof_bit_lengths,
} = range_proof_context;
if source_elgamal_pubkey_from_equality_proof != source_elgamal_pubkey_from_validity_proof {
return Err(TokenProofExtractionError::ElGamalPubkeyMismatch);
}
let burn_amount_commitment_lo = burn_amount_ciphertext_lo.extract_commitment();
let burn_amount_commitment_hi = burn_amount_ciphertext_hi.extract_commitment();
let expected_commitments = [
*remaining_balance_commitment,
burn_amount_commitment_lo,
burn_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 REMAINING_BALANCE_BIT_LENGTH: u8 = 64;
const BURN_AMOUNT_LO_BIT_LENGTH: u8 = 16;
const BURN_AMOUNT_HI_BIT_LENGTH: u8 = 32;
const PADDING_BIT_LENGTH: u8 = 16;
let expected_bit_lengths = [
REMAINING_BALANCE_BIT_LENGTH,
BURN_AMOUNT_LO_BIT_LENGTH,
BURN_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 burn_pubkeys = BurnPubkeys {
source: *source_elgamal_pubkey_from_equality_proof,
auditor: *auditor_elgamal_pubkey,
supply: *supply_elgamal_pubkey,
};
Ok(BurnProofContext {
burn_amount_ciphertext_lo: PodBurnAmountCiphertext(*burn_amount_ciphertext_lo),
burn_amount_ciphertext_hi: PodBurnAmountCiphertext(*burn_amount_ciphertext_hi),
burn_pubkeys,
remaining_balance_ciphertext: *remaining_balance_ciphertext,
})
}
}