zk-token-sdk: change variable names to use suffix rather than prefix (#23474)

* zk-token-sdk: change variable names to use suffix rather than prefix for type

* zk-token-sdk: cargo fmt
This commit is contained in:
samkim-crypto
2022-03-03 15:07:27 -05:00
committed by GitHub
parent f2fa49a771
commit 8d53ea81e9
9 changed files with 731 additions and 714 deletions

View File

@ -37,25 +37,25 @@ const TRANSFER_AMOUNT_HI_BIT_LENGTH: usize = 32;
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
pub struct TransferAmountEncryption { pub struct TransferAmountEncryption {
pub commitment: PedersenCommitment, pub commitment: PedersenCommitment,
pub handle_source: DecryptHandle, pub source_handle: DecryptHandle,
pub handle_dest: DecryptHandle, pub destination_handle: DecryptHandle,
pub handle_auditor: DecryptHandle, pub auditor_handle: DecryptHandle,
} }
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
impl TransferAmountEncryption { impl TransferAmountEncryption {
pub fn new( pub fn new(
amount: u32, amount: u32,
pubkey_source: &ElGamalPubkey, source_pubkey: &ElGamalPubkey,
pubkey_dest: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey,
pubkey_auditor: &ElGamalPubkey, auditor_pubkey: &ElGamalPubkey,
) -> (Self, PedersenOpening) { ) -> (Self, PedersenOpening) {
let (commitment, opening) = Pedersen::new(amount); let (commitment, opening) = Pedersen::new(amount);
let transfer_amount_encryption = Self { let transfer_amount_encryption = Self {
commitment, commitment,
handle_source: pubkey_source.decrypt_handle(&opening), source_handle: source_pubkey.decrypt_handle(&opening),
handle_dest: pubkey_dest.decrypt_handle(&opening), destination_handle: destination_pubkey.decrypt_handle(&opening),
handle_auditor: pubkey_auditor.decrypt_handle(&opening), auditor_handle: auditor_pubkey.decrypt_handle(&opening),
}; };
(transfer_amount_encryption, opening) (transfer_amount_encryption, opening)
@ -64,9 +64,9 @@ impl TransferAmountEncryption {
pub fn to_pod(&self) -> pod::TransferAmountEncryption { pub fn to_pod(&self) -> pod::TransferAmountEncryption {
pod::TransferAmountEncryption { pod::TransferAmountEncryption {
commitment: self.commitment.into(), commitment: self.commitment.into(),
handle_source: self.handle_source.into(), source_handle: self.source_handle.into(),
handle_dest: self.handle_dest.into(), destination_handle: self.destination_handle.into(),
handle_auditor: self.handle_auditor.into(), auditor_handle: self.auditor_handle.into(),
} }
} }
} }
@ -84,7 +84,7 @@ pub struct TransferData {
pub transfer_pubkeys: pod::TransferPubkeys, pub transfer_pubkeys: pod::TransferPubkeys,
/// The final spendable ciphertext after the transfer /// The final spendable ciphertext after the transfer
pub ciphertext_new_source: pod::ElGamalCiphertext, pub new_source_ciphertext: pod::ElGamalCiphertext,
/// Zero-knowledge proofs for Transfer /// Zero-knowledge proofs for Transfer
pub proof: TransferProof, pub proof: TransferProof,
@ -96,23 +96,23 @@ impl TransferData {
pub fn new( pub fn new(
transfer_amount: u64, transfer_amount: u64,
(spendable_balance, ciphertext_old_source): (u64, &ElGamalCiphertext), (spendable_balance, ciphertext_old_source): (u64, &ElGamalCiphertext),
keypair_source: &ElGamalKeypair, source_keypair: &ElGamalKeypair,
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
) -> Result<Self, ProofError> { ) -> Result<Self, ProofError> {
// split and encrypt transfer amount // split and encrypt transfer amount
let (amount_lo, amount_hi) = split_u64_into_u32(transfer_amount); let (amount_lo, amount_hi) = split_u64_into_u32(transfer_amount);
let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new( let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new(
amount_lo, amount_lo,
&keypair_source.public, &source_keypair.public,
pubkey_dest, destination_pubkey,
pubkey_auditor, auditor_pubkey,
); );
let (ciphertext_hi, opening_hi) = TransferAmountEncryption::new( let (ciphertext_hi, opening_hi) = TransferAmountEncryption::new(
amount_hi, amount_hi,
&keypair_source.public, &source_keypair.public,
pubkey_dest, destination_pubkey,
pubkey_auditor, auditor_pubkey,
); );
// subtract transfer amount from the spendable ciphertext // subtract transfer amount from the spendable ciphertext
@ -122,41 +122,41 @@ impl TransferData {
let transfer_amount_lo_source = ElGamalCiphertext { let transfer_amount_lo_source = ElGamalCiphertext {
commitment: ciphertext_lo.commitment, commitment: ciphertext_lo.commitment,
handle: ciphertext_lo.handle_source, handle: ciphertext_lo.source_handle,
}; };
let transfer_amount_hi_source = ElGamalCiphertext { let transfer_amount_hi_source = ElGamalCiphertext {
commitment: ciphertext_hi.commitment, commitment: ciphertext_hi.commitment,
handle: ciphertext_hi.handle_source, handle: ciphertext_hi.source_handle,
}; };
let ciphertext_new_source = ciphertext_old_source let new_source_ciphertext = ciphertext_old_source
- combine_u32_ciphertexts(&transfer_amount_lo_source, &transfer_amount_hi_source); - combine_u32_ciphertexts(&transfer_amount_lo_source, &transfer_amount_hi_source);
// generate transcript and append all public inputs // generate transcript and append all public inputs
let pod_transfer_pubkeys = pod::TransferPubkeys { let pod_transfer_pubkeys = pod::TransferPubkeys {
pubkey_source: keypair_source.public.into(), source_pubkey: source_keypair.public.into(),
pubkey_dest: (*pubkey_dest).into(), destination_pubkey: (*destination_pubkey).into(),
pubkey_auditor: (*pubkey_auditor).into(), auditor_pubkey: (*auditor_pubkey).into(),
}; };
let pod_ciphertext_lo: pod::TransferAmountEncryption = ciphertext_lo.into(); let pod_ciphertext_lo: pod::TransferAmountEncryption = ciphertext_lo.into();
let pod_ciphertext_hi: pod::TransferAmountEncryption = ciphertext_hi.into(); let pod_ciphertext_hi: pod::TransferAmountEncryption = ciphertext_hi.into();
let pod_ciphertext_new_source: pod::ElGamalCiphertext = ciphertext_new_source.into(); let pod_new_source_ciphertext: pod::ElGamalCiphertext = new_source_ciphertext.into();
let mut transcript = TransferProof::transcript_new( let mut transcript = TransferProof::transcript_new(
&pod_transfer_pubkeys, &pod_transfer_pubkeys,
&pod_ciphertext_lo, &pod_ciphertext_lo,
&pod_ciphertext_hi, &pod_ciphertext_hi,
&pod_ciphertext_new_source, &pod_new_source_ciphertext,
); );
let proof = TransferProof::new( let proof = TransferProof::new(
(amount_lo, amount_hi), (amount_lo, amount_hi),
keypair_source, source_keypair,
(pubkey_dest, pubkey_auditor), (destination_pubkey, auditor_pubkey),
&opening_lo, &opening_lo,
&opening_hi, &opening_hi,
(new_spendable_balance, &ciphertext_new_source), (new_spendable_balance, &new_source_ciphertext),
&mut transcript, &mut transcript,
); );
@ -164,7 +164,7 @@ impl TransferData {
ciphertext_lo: pod_ciphertext_lo, ciphertext_lo: pod_ciphertext_lo,
ciphertext_hi: pod_ciphertext_hi, ciphertext_hi: pod_ciphertext_hi,
transfer_pubkeys: pod_transfer_pubkeys, transfer_pubkeys: pod_transfer_pubkeys,
ciphertext_new_source: pod_ciphertext_new_source, new_source_ciphertext: pod_new_source_ciphertext,
proof, proof,
}) })
} }
@ -174,9 +174,9 @@ impl TransferData {
let ciphertext_lo: TransferAmountEncryption = self.ciphertext_lo.try_into()?; let ciphertext_lo: TransferAmountEncryption = self.ciphertext_lo.try_into()?;
let handle_lo = match role { let handle_lo = match role {
Role::Source => ciphertext_lo.handle_source, Role::Source => ciphertext_lo.source_handle,
Role::Dest => ciphertext_lo.handle_dest, Role::Dest => ciphertext_lo.destination_handle,
Role::Auditor => ciphertext_lo.handle_auditor, Role::Auditor => ciphertext_lo.auditor_handle,
}; };
Ok(ElGamalCiphertext { Ok(ElGamalCiphertext {
@ -190,9 +190,9 @@ impl TransferData {
let ciphertext_hi: TransferAmountEncryption = self.ciphertext_hi.try_into()?; let ciphertext_hi: TransferAmountEncryption = self.ciphertext_hi.try_into()?;
let handle_hi = match role { let handle_hi = match role {
Role::Source => ciphertext_hi.handle_source, Role::Source => ciphertext_hi.source_handle,
Role::Dest => ciphertext_hi.handle_dest, Role::Dest => ciphertext_hi.destination_handle,
Role::Auditor => ciphertext_hi.handle_auditor, Role::Auditor => ciphertext_hi.auditor_handle,
}; };
Ok(ElGamalCiphertext { Ok(ElGamalCiphertext {
@ -230,13 +230,13 @@ impl Verifiable for TransferData {
&self.transfer_pubkeys, &self.transfer_pubkeys,
&self.ciphertext_lo, &self.ciphertext_lo,
&self.ciphertext_hi, &self.ciphertext_hi,
&self.ciphertext_new_source, &self.new_source_ciphertext,
); );
let ciphertext_lo = self.ciphertext_lo.try_into()?; let ciphertext_lo = self.ciphertext_lo.try_into()?;
let ciphertext_hi = self.ciphertext_hi.try_into()?; let ciphertext_hi = self.ciphertext_hi.try_into()?;
let transfer_pubkeys = self.transfer_pubkeys.try_into()?; let transfer_pubkeys = self.transfer_pubkeys.try_into()?;
let new_spendable_ciphertext = self.ciphertext_new_source.try_into()?; let new_spendable_ciphertext = self.new_source_ciphertext.try_into()?;
self.proof.verify( self.proof.verify(
&ciphertext_lo, &ciphertext_lo,
@ -272,56 +272,56 @@ impl TransferProof {
transfer_pubkeys: &pod::TransferPubkeys, transfer_pubkeys: &pod::TransferPubkeys,
ciphertext_lo: &pod::TransferAmountEncryption, ciphertext_lo: &pod::TransferAmountEncryption,
ciphertext_hi: &pod::TransferAmountEncryption, ciphertext_hi: &pod::TransferAmountEncryption,
ciphertext_new_source: &pod::ElGamalCiphertext, new_source_ciphertext: &pod::ElGamalCiphertext,
) -> Transcript { ) -> Transcript {
let mut transcript = Transcript::new(b"transfer-proof"); let mut transcript = Transcript::new(b"transfer-proof");
transcript.append_pubkey(b"pubkey-source", &transfer_pubkeys.pubkey_source); transcript.append_pubkey(b"pubkey-source", &transfer_pubkeys.source_pubkey);
transcript.append_pubkey(b"pubkey-dest", &transfer_pubkeys.pubkey_dest); transcript.append_pubkey(b"pubkey-dest", &transfer_pubkeys.destination_pubkey);
transcript.append_pubkey(b"pubkey-auditor", &transfer_pubkeys.pubkey_auditor); transcript.append_pubkey(b"pubkey-auditor", &transfer_pubkeys.auditor_pubkey);
transcript.append_commitment(b"comm-lo-amount", &ciphertext_lo.commitment); transcript.append_commitment(b"comm-lo-amount", &ciphertext_lo.commitment);
transcript.append_handle(b"handle-lo-source", &ciphertext_lo.handle_source); transcript.append_handle(b"handle-lo-source", &ciphertext_lo.source_handle);
transcript.append_handle(b"handle-lo-dest", &ciphertext_lo.handle_dest); transcript.append_handle(b"handle-lo-dest", &ciphertext_lo.destination_handle);
transcript.append_handle(b"handle-lo-auditor", &ciphertext_lo.handle_auditor); transcript.append_handle(b"handle-lo-auditor", &ciphertext_lo.auditor_handle);
transcript.append_commitment(b"comm-hi-amount", &ciphertext_hi.commitment); transcript.append_commitment(b"comm-hi-amount", &ciphertext_hi.commitment);
transcript.append_handle(b"handle-hi-source", &ciphertext_hi.handle_source); transcript.append_handle(b"handle-hi-source", &ciphertext_hi.source_handle);
transcript.append_handle(b"handle-hi-dest", &ciphertext_hi.handle_dest); transcript.append_handle(b"handle-hi-dest", &ciphertext_hi.destination_handle);
transcript.append_handle(b"handle-hi-auditor", &ciphertext_hi.handle_auditor); transcript.append_handle(b"handle-hi-auditor", &ciphertext_hi.auditor_handle);
transcript.append_ciphertext(b"ciphertext-new-source", ciphertext_new_source); transcript.append_ciphertext(b"ciphertext-new-source", new_source_ciphertext);
transcript transcript
} }
pub fn new( pub fn new(
(transfer_amount_lo, transfer_amount_hi): (u32, u32), (transfer_amount_lo, transfer_amount_hi): (u32, u32),
keypair_source: &ElGamalKeypair, source_keypair: &ElGamalKeypair,
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
opening_lo: &PedersenOpening, opening_lo: &PedersenOpening,
opening_hi: &PedersenOpening, opening_hi: &PedersenOpening,
(source_new_balance, ciphertext_new_source): (u64, &ElGamalCiphertext), (source_new_balance, new_source_ciphertext): (u64, &ElGamalCiphertext),
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Self { ) -> Self {
// generate a Pedersen commitment for the remaining balance in source // generate a Pedersen commitment for the remaining balance in source
let (commitment_new_source, opening_source) = Pedersen::new(source_new_balance); let (commitment_new_source, source_opening) = Pedersen::new(source_new_balance);
let pod_commitment_new_source: pod::PedersenCommitment = commitment_new_source.into(); let pod_commitment_new_source: pod::PedersenCommitment = commitment_new_source.into();
transcript.append_commitment(b"commitment-new-source", &pod_commitment_new_source); transcript.append_commitment(b"commitment-new-source", &pod_commitment_new_source);
// generate equality_proof // generate equality_proof
let equality_proof = CtxtCommEqualityProof::new( let equality_proof = CtxtCommEqualityProof::new(
keypair_source, source_keypair,
ciphertext_new_source, new_source_ciphertext,
source_new_balance, source_new_balance,
&opening_source, &source_opening,
transcript, transcript,
); );
// generate ciphertext validity proof // generate ciphertext validity proof
let validity_proof = AggregatedValidityProof::new( let validity_proof = AggregatedValidityProof::new(
(pubkey_dest, pubkey_auditor), (destination_pubkey, auditor_pubkey),
(transfer_amount_lo, transfer_amount_hi), (transfer_amount_lo, transfer_amount_hi),
(opening_lo, opening_hi), (opening_lo, opening_hi),
transcript, transcript,
@ -339,7 +339,7 @@ impl TransferProof {
TRANSFER_AMOUNT_LO_BIT_LENGTH, TRANSFER_AMOUNT_LO_BIT_LENGTH,
TRANSFER_AMOUNT_HI_BIT_LENGTH, TRANSFER_AMOUNT_HI_BIT_LENGTH,
], ],
vec![&opening_source, opening_lo, opening_hi], vec![&source_opening, opening_lo, opening_hi],
transcript, transcript,
); );
@ -370,7 +370,7 @@ impl TransferProof {
// //
// TODO: we can also consider verifying equality and range proof in a batch // TODO: we can also consider verifying equality and range proof in a batch
equality_proof.verify( equality_proof.verify(
&transfer_pubkeys.pubkey_source, &transfer_pubkeys.source_pubkey,
ciphertext_new_spendable, ciphertext_new_spendable,
&commitment, &commitment,
transcript, transcript,
@ -379,12 +379,15 @@ impl TransferProof {
// verify validity proof // verify validity proof
aggregated_validity_proof.verify( aggregated_validity_proof.verify(
( (
&transfer_pubkeys.pubkey_dest, &transfer_pubkeys.destination_pubkey,
&transfer_pubkeys.pubkey_auditor, &transfer_pubkeys.auditor_pubkey,
), ),
(&ciphertext_lo.commitment, &ciphertext_hi.commitment), (&ciphertext_lo.commitment, &ciphertext_hi.commitment),
(&ciphertext_lo.handle_dest, &ciphertext_hi.handle_dest), (
(&ciphertext_lo.handle_auditor, &ciphertext_hi.handle_auditor), &ciphertext_lo.destination_handle,
&ciphertext_hi.destination_handle,
),
(&ciphertext_lo.auditor_handle, &ciphertext_hi.auditor_handle),
transcript, transcript,
)?; )?;
@ -409,9 +412,9 @@ impl TransferProof {
#[repr(C)] #[repr(C)]
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
pub struct TransferPubkeys { pub struct TransferPubkeys {
pub pubkey_source: ElGamalPubkey, pub source_pubkey: ElGamalPubkey,
pub pubkey_dest: ElGamalPubkey, pub destination_pubkey: ElGamalPubkey,
pub pubkey_auditor: ElGamalPubkey, pub auditor_pubkey: ElGamalPubkey,
} }
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
@ -419,26 +422,27 @@ impl TransferPubkeys {
// TODO: use constructor instead // TODO: use constructor instead
pub fn to_bytes(&self) -> [u8; 96] { pub fn to_bytes(&self) -> [u8; 96] {
let mut bytes = [0u8; 96]; let mut bytes = [0u8; 96];
bytes[..32].copy_from_slice(&self.pubkey_source.to_bytes()); bytes[..32].copy_from_slice(&self.source_pubkey.to_bytes());
bytes[32..64].copy_from_slice(&self.pubkey_dest.to_bytes()); bytes[32..64].copy_from_slice(&self.destination_pubkey.to_bytes());
bytes[64..96].copy_from_slice(&self.pubkey_auditor.to_bytes()); bytes[64..96].copy_from_slice(&self.auditor_pubkey.to_bytes());
bytes bytes
} }
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ProofError> { pub fn from_bytes(bytes: &[u8]) -> Result<Self, ProofError> {
let bytes = array_ref![bytes, 0, 96]; let bytes = array_ref![bytes, 0, 96];
let (pubkey_source, pubkey_dest, pubkey_auditor) = array_refs![bytes, 32, 32, 32]; let (source_pubkey, destination_pubkey, auditor_pubkey) = array_refs![bytes, 32, 32, 32];
let pubkey_source = let source_pubkey =
ElGamalPubkey::from_bytes(pubkey_source).ok_or(ProofError::Verification)?; ElGamalPubkey::from_bytes(source_pubkey).ok_or(ProofError::Verification)?;
let pubkey_dest = ElGamalPubkey::from_bytes(pubkey_dest).ok_or(ProofError::Verification)?; let destination_pubkey =
let pubkey_auditor = ElGamalPubkey::from_bytes(destination_pubkey).ok_or(ProofError::Verification)?;
ElGamalPubkey::from_bytes(pubkey_auditor).ok_or(ProofError::Verification)?; let auditor_pubkey =
ElGamalPubkey::from_bytes(auditor_pubkey).ok_or(ProofError::Verification)?;
Ok(Self { Ok(Self {
pubkey_source, source_pubkey,
pubkey_dest, destination_pubkey,
pubkey_auditor, auditor_pubkey,
}) })
} }
} }

View File

@ -63,10 +63,10 @@ pub struct TransferWithFeeData {
pub transfer_with_fee_pubkeys: pod::TransferWithFeePubkeys, pub transfer_with_fee_pubkeys: pod::TransferWithFeePubkeys,
/// The final spendable ciphertext after the transfer, /// The final spendable ciphertext after the transfer,
pub ciphertext_new_source: pod::ElGamalCiphertext, pub new_source_ciphertext: pod::ElGamalCiphertext,
// transfer fee encryption // transfer fee encryption
pub ciphertext_fee: pod::FeeEncryption, pub fee_ciphertext: pod::FeeEncryption,
// fee parameters // fee parameters
pub fee_parameters: pod::FeeParameters, pub fee_parameters: pod::FeeParameters,
@ -79,26 +79,26 @@ pub struct TransferWithFeeData {
impl TransferWithFeeData { impl TransferWithFeeData {
pub fn new( pub fn new(
transfer_amount: u64, transfer_amount: u64,
(spendable_balance, ciphertext_old_source): (u64, &ElGamalCiphertext), (spendable_balance, old_source_ciphertext): (u64, &ElGamalCiphertext),
keypair_source: &ElGamalKeypair, source_keypair: &ElGamalKeypair,
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
fee_parameters: FeeParameters, fee_parameters: FeeParameters,
pubkey_withdraw_withheld_authority: &ElGamalPubkey, withdraw_withheld_authority_pubkey: &ElGamalPubkey,
) -> Result<Self, ProofError> { ) -> Result<Self, ProofError> {
// split and encrypt transfer amount // split and encrypt transfer amount
let (amount_lo, amount_hi) = split_u64_into_u32(transfer_amount); let (amount_lo, amount_hi) = split_u64_into_u32(transfer_amount);
let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new( let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new(
amount_lo, amount_lo,
&keypair_source.public, &source_keypair.public,
pubkey_dest, destination_pubkey,
pubkey_auditor, auditor_pubkey,
); );
let (ciphertext_hi, opening_hi) = TransferAmountEncryption::new( let (ciphertext_hi, opening_hi) = TransferAmountEncryption::new(
amount_hi, amount_hi,
&keypair_source.public, &source_keypair.public,
pubkey_dest, destination_pubkey,
pubkey_auditor, auditor_pubkey,
); );
// subtract transfer amount from the spendable ciphertext // subtract transfer amount from the spendable ciphertext
@ -108,15 +108,15 @@ impl TransferWithFeeData {
let transfer_amount_lo_source = ElGamalCiphertext { let transfer_amount_lo_source = ElGamalCiphertext {
commitment: ciphertext_lo.commitment, commitment: ciphertext_lo.commitment,
handle: ciphertext_lo.handle_source, handle: ciphertext_lo.source_handle,
}; };
let transfer_amount_hi_source = ElGamalCiphertext { let transfer_amount_hi_source = ElGamalCiphertext {
commitment: ciphertext_hi.commitment, commitment: ciphertext_hi.commitment,
handle: ciphertext_hi.handle_source, handle: ciphertext_hi.source_handle,
}; };
let ciphertext_new_source = ciphertext_old_source let new_source_ciphertext = old_source_ciphertext
- combine_u32_ciphertexts(&transfer_amount_lo_source, &transfer_amount_hi_source); - combine_u32_ciphertexts(&transfer_amount_lo_source, &transfer_amount_hi_source);
// calculate and encrypt fee // calculate and encrypt fee
@ -126,43 +126,42 @@ impl TransferWithFeeData {
let below_max = u64::ct_gt(&fee_parameters.maximum_fee, &fee_amount); let below_max = u64::ct_gt(&fee_parameters.maximum_fee, &fee_amount);
let fee_to_encrypt = let fee_to_encrypt =
u64::conditional_select(&fee_parameters.maximum_fee, &fee_amount, below_max); u64::conditional_select(&fee_parameters.maximum_fee, &fee_amount, below_max);
// u64::conditional_select(&fee_amount, &fee_parameters.maximum_fee, below_max);
let (ciphertext_fee, opening_fee) = FeeEncryption::new( let (fee_ciphertext, opening_fee) = FeeEncryption::new(
fee_to_encrypt, fee_to_encrypt,
pubkey_dest, destination_pubkey,
pubkey_withdraw_withheld_authority, withdraw_withheld_authority_pubkey,
); );
// generate transcript and append all public inputs // generate transcript and append all public inputs
let pod_transfer_with_fee_pubkeys = pod::TransferWithFeePubkeys { let pod_transfer_with_fee_pubkeys = pod::TransferWithFeePubkeys {
pubkey_source: keypair_source.public.into(), source_pubkey: source_keypair.public.into(),
pubkey_dest: (*pubkey_dest).into(), destination_pubkey: (*destination_pubkey).into(),
pubkey_auditor: (*pubkey_auditor).into(), auditor_pubkey: (*auditor_pubkey).into(),
pubkey_withdraw_withheld_authority: (*pubkey_withdraw_withheld_authority).into(), withdraw_withheld_authority_pubkey: (*withdraw_withheld_authority_pubkey).into(),
}; };
let pod_ciphertext_lo: pod::TransferAmountEncryption = ciphertext_lo.to_pod(); let pod_ciphertext_lo: pod::TransferAmountEncryption = ciphertext_lo.to_pod();
let pod_ciphertext_hi: pod::TransferAmountEncryption = ciphertext_hi.to_pod(); let pod_ciphertext_hi: pod::TransferAmountEncryption = ciphertext_hi.to_pod();
let pod_ciphertext_new_source: pod::ElGamalCiphertext = ciphertext_new_source.into(); let pod_new_source_ciphertext: pod::ElGamalCiphertext = new_source_ciphertext.into();
let pod_ciphertext_fee: pod::FeeEncryption = ciphertext_fee.to_pod(); let pod_fee_ciphertext: pod::FeeEncryption = fee_ciphertext.to_pod();
let mut transcript = TransferWithFeeProof::transcript_new( let mut transcript = TransferWithFeeProof::transcript_new(
&pod_transfer_with_fee_pubkeys, &pod_transfer_with_fee_pubkeys,
&pod_ciphertext_lo, &pod_ciphertext_lo,
&pod_ciphertext_hi, &pod_ciphertext_hi,
&pod_ciphertext_new_source, &pod_new_source_ciphertext,
&pod_ciphertext_fee, &pod_fee_ciphertext,
); );
let proof = TransferWithFeeProof::new( let proof = TransferWithFeeProof::new(
(amount_lo, &ciphertext_lo, &opening_lo), (amount_lo, &ciphertext_lo, &opening_lo),
(amount_hi, &ciphertext_hi, &opening_hi), (amount_hi, &ciphertext_hi, &opening_hi),
keypair_source, source_keypair,
(pubkey_dest, pubkey_auditor), (destination_pubkey, auditor_pubkey),
(new_spendable_balance, &ciphertext_new_source), (new_spendable_balance, &new_source_ciphertext),
(fee_amount, &ciphertext_fee, &opening_fee), (fee_to_encrypt, &fee_ciphertext, &opening_fee),
delta_fee, delta_fee,
pubkey_withdraw_withheld_authority, withdraw_withheld_authority_pubkey,
fee_parameters, fee_parameters,
&mut transcript, &mut transcript,
); );
@ -171,8 +170,8 @@ impl TransferWithFeeData {
ciphertext_lo: pod_ciphertext_lo, ciphertext_lo: pod_ciphertext_lo,
ciphertext_hi: pod_ciphertext_hi, ciphertext_hi: pod_ciphertext_hi,
transfer_with_fee_pubkeys: pod_transfer_with_fee_pubkeys, transfer_with_fee_pubkeys: pod_transfer_with_fee_pubkeys,
ciphertext_new_source: pod_ciphertext_new_source, new_source_ciphertext: pod_new_source_ciphertext,
ciphertext_fee: pod_ciphertext_fee, fee_ciphertext: pod_fee_ciphertext,
fee_parameters: fee_parameters.into(), fee_parameters: fee_parameters.into(),
proof, proof,
}) })
@ -183,9 +182,9 @@ impl TransferWithFeeData {
let ciphertext_lo: TransferAmountEncryption = self.ciphertext_lo.try_into()?; let ciphertext_lo: TransferAmountEncryption = self.ciphertext_lo.try_into()?;
let handle_lo = match role { let handle_lo = match role {
Role::Source => ciphertext_lo.handle_source, Role::Source => ciphertext_lo.source_handle,
Role::Dest => ciphertext_lo.handle_dest, Role::Dest => ciphertext_lo.destination_handle,
Role::Auditor => ciphertext_lo.handle_auditor, Role::Auditor => ciphertext_lo.auditor_handle,
}; };
Ok(ElGamalCiphertext { Ok(ElGamalCiphertext {
@ -199,9 +198,9 @@ impl TransferWithFeeData {
let ciphertext_hi: TransferAmountEncryption = self.ciphertext_hi.try_into()?; let ciphertext_hi: TransferAmountEncryption = self.ciphertext_hi.try_into()?;
let handle_hi = match role { let handle_hi = match role {
Role::Source => ciphertext_hi.handle_source, Role::Source => ciphertext_hi.source_handle,
Role::Dest => ciphertext_hi.handle_dest, Role::Dest => ciphertext_hi.destination_handle,
Role::Auditor => ciphertext_hi.handle_auditor, Role::Auditor => ciphertext_hi.auditor_handle,
}; };
Ok(ElGamalCiphertext { Ok(ElGamalCiphertext {
@ -238,24 +237,24 @@ impl Verifiable for TransferWithFeeData {
&self.transfer_with_fee_pubkeys, &self.transfer_with_fee_pubkeys,
&self.ciphertext_lo, &self.ciphertext_lo,
&self.ciphertext_hi, &self.ciphertext_hi,
&self.ciphertext_new_source, &self.new_source_ciphertext,
&self.ciphertext_fee, &self.fee_ciphertext,
); );
let ciphertext_lo = self.ciphertext_lo.try_into()?; let ciphertext_lo = self.ciphertext_lo.try_into()?;
let ciphertext_hi = self.ciphertext_hi.try_into()?; let ciphertext_hi = self.ciphertext_hi.try_into()?;
let pubkeys_transfer_with_fee = self.transfer_with_fee_pubkeys.try_into()?; let pubkeys_transfer_with_fee = self.transfer_with_fee_pubkeys.try_into()?;
let ciphertext_new_source = self.ciphertext_new_source.try_into()?; let new_source_ciphertext = self.new_source_ciphertext.try_into()?;
let ciphertext_fee = self.ciphertext_fee.try_into()?; let fee_ciphertext = self.fee_ciphertext.try_into()?;
let fee_parameters = self.fee_parameters.into(); let fee_parameters = self.fee_parameters.into();
self.proof.verify( self.proof.verify(
&ciphertext_lo, &ciphertext_lo,
&ciphertext_hi, &ciphertext_hi,
&pubkeys_transfer_with_fee, &pubkeys_transfer_with_fee,
&ciphertext_new_source, &new_source_ciphertext,
&ciphertext_fee, &fee_ciphertext,
fee_parameters, fee_parameters,
&mut transcript, &mut transcript,
) )
@ -266,12 +265,12 @@ impl Verifiable for TransferWithFeeData {
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]
pub struct TransferWithFeeProof { pub struct TransferWithFeeProof {
pub commitment_new_source: pod::PedersenCommitment, pub new_source_commitment: pod::PedersenCommitment,
pub commitment_claimed: pod::PedersenCommitment, pub claimed_commitment: pod::PedersenCommitment,
pub equality_proof: pod::CtxtCommEqualityProof, pub equality_proof: pod::CtxtCommEqualityProof,
pub ciphertext_amount_validity_proof: pod::AggregatedValidityProof, pub ciphertext_amount_validity_proof: pod::AggregatedValidityProof,
pub fee_sigma_proof: pod::FeeSigmaProof, pub fee_sigma_proof: pod::FeeSigmaProof,
pub ciphertext_fee_validity_proof: pod::ValidityProof, pub fee_ciphertext_validity_proof: pod::ValidityProof,
pub range_proof: pod::RangeProof256, pub range_proof: pod::RangeProof256,
} }
@ -282,36 +281,39 @@ impl TransferWithFeeProof {
transfer_with_fee_pubkeys: &pod::TransferWithFeePubkeys, transfer_with_fee_pubkeys: &pod::TransferWithFeePubkeys,
ciphertext_lo: &pod::TransferAmountEncryption, ciphertext_lo: &pod::TransferAmountEncryption,
ciphertext_hi: &pod::TransferAmountEncryption, ciphertext_hi: &pod::TransferAmountEncryption,
ciphertext_new_source: &pod::ElGamalCiphertext, new_source_ciphertext: &pod::ElGamalCiphertext,
ciphertext_fee: &pod::FeeEncryption, fee_ciphertext: &pod::FeeEncryption,
) -> Transcript { ) -> Transcript {
let mut transcript = Transcript::new(b"FeeProof"); let mut transcript = Transcript::new(b"FeeProof");
transcript.append_pubkey(b"pubkey-source", &transfer_with_fee_pubkeys.pubkey_source); transcript.append_pubkey(b"pubkey-source", &transfer_with_fee_pubkeys.source_pubkey);
transcript.append_pubkey(b"pubkey-dest", &transfer_with_fee_pubkeys.pubkey_dest);
transcript.append_pubkey(b"pubkey-auditor", &transfer_with_fee_pubkeys.pubkey_auditor);
transcript.append_pubkey( transcript.append_pubkey(
b"pubkey_withdraw_withheld_authority", b"pubkey-dest",
&transfer_with_fee_pubkeys.pubkey_withdraw_withheld_authority, &transfer_with_fee_pubkeys.destination_pubkey,
);
transcript.append_pubkey(b"pubkey-auditor", &transfer_with_fee_pubkeys.auditor_pubkey);
transcript.append_pubkey(
b"withdraw_withheld_authority_pubkey",
&transfer_with_fee_pubkeys.withdraw_withheld_authority_pubkey,
); );
transcript.append_commitment(b"comm-lo-amount", &ciphertext_lo.commitment); transcript.append_commitment(b"comm-lo-amount", &ciphertext_lo.commitment);
transcript.append_handle(b"handle-lo-source", &ciphertext_lo.handle_source); transcript.append_handle(b"handle-lo-source", &ciphertext_lo.source_handle);
transcript.append_handle(b"handle-lo-dest", &ciphertext_lo.handle_dest); transcript.append_handle(b"handle-lo-dest", &ciphertext_lo.destination_handle);
transcript.append_handle(b"handle-lo-auditor", &ciphertext_lo.handle_auditor); transcript.append_handle(b"handle-lo-auditor", &ciphertext_lo.auditor_handle);
transcript.append_commitment(b"comm-hi-amount", &ciphertext_hi.commitment); transcript.append_commitment(b"comm-hi-amount", &ciphertext_hi.commitment);
transcript.append_handle(b"handle-hi-source", &ciphertext_hi.handle_source); transcript.append_handle(b"handle-hi-source", &ciphertext_hi.source_handle);
transcript.append_handle(b"handle-hi-dest", &ciphertext_hi.handle_dest); transcript.append_handle(b"handle-hi-dest", &ciphertext_hi.destination_handle);
transcript.append_handle(b"handle-hi-auditor", &ciphertext_hi.handle_auditor); transcript.append_handle(b"handle-hi-auditor", &ciphertext_hi.auditor_handle);
transcript.append_ciphertext(b"ctxt-new-source", ciphertext_new_source); transcript.append_ciphertext(b"ctxt-new-source", new_source_ciphertext);
transcript.append_commitment(b"comm-fee", &ciphertext_fee.commitment); transcript.append_commitment(b"comm-fee", &fee_ciphertext.commitment);
transcript.append_handle(b"fee-dest-handle", &ciphertext_fee.handle_dest); transcript.append_handle(b"fee-dest-handle", &fee_ciphertext.destination_handle);
transcript.append_handle( transcript.append_handle(
b"handle-fee-auditor", b"handle-fee-auditor",
&ciphertext_fee.handle_withdraw_withheld_authority, &fee_ciphertext.withdraw_withheld_authority_handle,
); );
transcript transcript
@ -322,13 +324,13 @@ impl TransferWithFeeProof {
pub fn new( pub fn new(
transfer_amount_lo_data: (u32, &TransferAmountEncryption, &PedersenOpening), transfer_amount_lo_data: (u32, &TransferAmountEncryption, &PedersenOpening),
transfer_amount_hi_data: (u32, &TransferAmountEncryption, &PedersenOpening), transfer_amount_hi_data: (u32, &TransferAmountEncryption, &PedersenOpening),
keypair_source: &ElGamalKeypair, source_keypair: &ElGamalKeypair,
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
(source_new_balance, ciphertext_new_source): (u64, &ElGamalCiphertext), (source_new_balance, new_source_ciphertext): (u64, &ElGamalCiphertext),
(fee_amount, ciphertext_fee, opening_fee): (u64, &FeeEncryption, &PedersenOpening), (fee_amount, fee_ciphertext, opening_fee): (u64, &FeeEncryption, &PedersenOpening),
delta_fee: u64, delta_fee: u64,
pubkey_withdraw_withheld_authority: &ElGamalPubkey, withdraw_withheld_authority_pubkey: &ElGamalPubkey,
fee_parameters: FeeParameters, fee_parameters: FeeParameters,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Self { ) -> Self {
@ -336,19 +338,19 @@ impl TransferWithFeeProof {
let (transfer_amount_hi, ciphertext_hi, opening_hi) = transfer_amount_hi_data; let (transfer_amount_hi, ciphertext_hi, opening_hi) = transfer_amount_hi_data;
// generate a Pedersen commitment for the remaining balance in source // generate a Pedersen commitment for the remaining balance in source
let (commitment_new_source, opening_source) = Pedersen::new(source_new_balance); let (new_source_commitment, opening_source) = Pedersen::new(source_new_balance);
let (commitment_claimed, opening_claimed) = Pedersen::new(delta_fee); let (claimed_commitment, opening_claimed) = Pedersen::new(delta_fee);
let pod_commitment_new_source: pod::PedersenCommitment = commitment_new_source.into(); let pod_new_source_commitment: pod::PedersenCommitment = new_source_commitment.into();
let pod_commitment_claimed: pod::PedersenCommitment = commitment_claimed.into(); let pod_claimed_commitment: pod::PedersenCommitment = claimed_commitment.into();
transcript.append_commitment(b"commitment-new-source", &pod_commitment_new_source); transcript.append_commitment(b"commitment-new-source", &pod_new_source_commitment);
transcript.append_commitment(b"commitment-claimed", &pod_commitment_claimed); transcript.append_commitment(b"commitment-claimed", &pod_claimed_commitment);
// generate equality_proof // generate equality_proof
let equality_proof = CtxtCommEqualityProof::new( let equality_proof = CtxtCommEqualityProof::new(
keypair_source, source_keypair,
ciphertext_new_source, new_source_ciphertext,
source_new_balance, source_new_balance,
&opening_source, &opening_source,
transcript, transcript,
@ -356,29 +358,29 @@ impl TransferWithFeeProof {
// generate ciphertext validity proof // generate ciphertext validity proof
let ciphertext_amount_validity_proof = AggregatedValidityProof::new( let ciphertext_amount_validity_proof = AggregatedValidityProof::new(
(pubkey_dest, pubkey_auditor), (destination_pubkey, auditor_pubkey),
(transfer_amount_lo, transfer_amount_hi), (transfer_amount_lo, transfer_amount_hi),
(opening_lo, opening_hi), (opening_lo, opening_hi),
transcript, transcript,
); );
let (commitment_delta, opening_delta) = compute_delta_commitment_and_opening( let (delta_commitment, opening_delta) = compute_delta_commitment_and_opening(
(&ciphertext_lo.commitment, opening_lo), (&ciphertext_lo.commitment, opening_lo),
(&ciphertext_hi.commitment, opening_hi), (&ciphertext_hi.commitment, opening_hi),
(&ciphertext_fee.commitment, opening_fee), (&fee_ciphertext.commitment, opening_fee),
fee_parameters.fee_rate_basis_points, fee_parameters.fee_rate_basis_points,
); );
let fee_sigma_proof = FeeSigmaProof::new( let fee_sigma_proof = FeeSigmaProof::new(
(fee_amount, &ciphertext_fee.commitment, opening_fee), (fee_amount, &fee_ciphertext.commitment, opening_fee),
(delta_fee, &commitment_delta, &opening_delta), (delta_fee, &delta_commitment, &opening_delta),
(&commitment_claimed, &opening_claimed), (&claimed_commitment, &opening_claimed),
fee_parameters.maximum_fee, fee_parameters.maximum_fee,
transcript, transcript,
); );
let ciphertext_fee_validity_proof = ValidityProof::new( let fee_ciphertext_validity_proof = ValidityProof::new(
(pubkey_dest, pubkey_withdraw_withheld_authority), (destination_pubkey, withdraw_withheld_authority_pubkey),
fee_amount, fee_amount,
opening_fee, opening_fee,
transcript, transcript,
@ -411,12 +413,12 @@ impl TransferWithFeeProof {
); );
Self { Self {
commitment_new_source: pod_commitment_new_source, new_source_commitment: pod_new_source_commitment,
commitment_claimed: pod_commitment_claimed, claimed_commitment: pod_claimed_commitment,
equality_proof: equality_proof.into(), equality_proof: equality_proof.into(),
ciphertext_amount_validity_proof: ciphertext_amount_validity_proof.into(), ciphertext_amount_validity_proof: ciphertext_amount_validity_proof.into(),
fee_sigma_proof: fee_sigma_proof.into(), fee_sigma_proof: fee_sigma_proof.into(),
ciphertext_fee_validity_proof: ciphertext_fee_validity_proof.into(), fee_ciphertext_validity_proof: fee_ciphertext_validity_proof.into(),
range_proof: range_proof.try_into().expect("range proof: length error"), range_proof: range_proof.try_into().expect("range proof: length error"),
} }
} }
@ -428,81 +430,86 @@ impl TransferWithFeeProof {
transfer_with_fee_pubkeys: &TransferWithFeePubkeys, transfer_with_fee_pubkeys: &TransferWithFeePubkeys,
new_spendable_ciphertext: &ElGamalCiphertext, new_spendable_ciphertext: &ElGamalCiphertext,
ciphertext_fee: &FeeEncryption, fee_ciphertext: &FeeEncryption,
fee_parameters: FeeParameters, fee_parameters: FeeParameters,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), ProofError> { ) -> Result<(), ProofError> {
transcript.append_commitment(b"commitment-new-source", &self.commitment_new_source); transcript.append_commitment(b"commitment-new-source", &self.new_source_commitment);
transcript.append_commitment(b"commitment-claimed", &self.commitment_claimed); transcript.append_commitment(b"commitment-claimed", &self.claimed_commitment);
let commitment_new_source: PedersenCommitment = self.commitment_new_source.try_into()?; let new_source_commitment: PedersenCommitment = self.new_source_commitment.try_into()?;
let commitment_claimed: PedersenCommitment = self.commitment_claimed.try_into()?; let claimed_commitment: PedersenCommitment = self.claimed_commitment.try_into()?;
let equality_proof: CtxtCommEqualityProof = self.equality_proof.try_into()?; let equality_proof: CtxtCommEqualityProof = self.equality_proof.try_into()?;
let ciphertext_amount_validity_proof: AggregatedValidityProof = let ciphertext_amount_validity_proof: AggregatedValidityProof =
self.ciphertext_amount_validity_proof.try_into()?; self.ciphertext_amount_validity_proof.try_into()?;
let fee_sigma_proof: FeeSigmaProof = self.fee_sigma_proof.try_into()?; let fee_sigma_proof: FeeSigmaProof = self.fee_sigma_proof.try_into()?;
let ciphertext_fee_validity_proof: ValidityProof = let fee_ciphertext_validity_proof: ValidityProof =
self.ciphertext_fee_validity_proof.try_into()?; self.fee_ciphertext_validity_proof.try_into()?;
let range_proof: RangeProof = self.range_proof.try_into()?; let range_proof: RangeProof = self.range_proof.try_into()?;
// verify equality proof // verify equality proof
equality_proof.verify( equality_proof.verify(
&transfer_with_fee_pubkeys.pubkey_source, &transfer_with_fee_pubkeys.source_pubkey,
new_spendable_ciphertext, new_spendable_ciphertext,
&commitment_new_source, &new_source_commitment,
transcript, transcript,
)?; )?;
println!("here");
// verify that the transfer amount is encrypted correctly // verify that the transfer amount is encrypted correctly
ciphertext_amount_validity_proof.verify( ciphertext_amount_validity_proof.verify(
( (
&transfer_with_fee_pubkeys.pubkey_dest, &transfer_with_fee_pubkeys.destination_pubkey,
&transfer_with_fee_pubkeys.pubkey_auditor, &transfer_with_fee_pubkeys.auditor_pubkey,
), ),
(&ciphertext_lo.commitment, &ciphertext_hi.commitment), (&ciphertext_lo.commitment, &ciphertext_hi.commitment),
(&ciphertext_lo.handle_dest, &ciphertext_hi.handle_dest), (
(&ciphertext_lo.handle_auditor, &ciphertext_hi.handle_auditor), &ciphertext_lo.destination_handle,
&ciphertext_hi.destination_handle,
),
(&ciphertext_lo.auditor_handle, &ciphertext_hi.auditor_handle),
transcript, transcript,
)?; )?;
// verify fee sigma proof // verify fee sigma proof
let commitment_delta = compute_delta_commitment( let delta_commitment = compute_delta_commitment(
&ciphertext_lo.commitment, &ciphertext_lo.commitment,
&ciphertext_hi.commitment, &ciphertext_hi.commitment,
&ciphertext_fee.commitment, &fee_ciphertext.commitment,
fee_parameters.fee_rate_basis_points, fee_parameters.fee_rate_basis_points,
); );
fee_sigma_proof.verify( fee_sigma_proof.verify(
&ciphertext_fee.commitment, &fee_ciphertext.commitment,
&commitment_delta, &delta_commitment,
&commitment_claimed, &claimed_commitment,
fee_parameters.maximum_fee, fee_parameters.maximum_fee,
transcript, transcript,
)?; )?;
ciphertext_fee_validity_proof.verify( fee_ciphertext_validity_proof.verify(
&ciphertext_fee.commitment, &fee_ciphertext.commitment,
( (
&transfer_with_fee_pubkeys.pubkey_dest, &transfer_with_fee_pubkeys.destination_pubkey,
&transfer_with_fee_pubkeys.pubkey_withdraw_withheld_authority, &transfer_with_fee_pubkeys.withdraw_withheld_authority_pubkey,
), ),
( (
&ciphertext_fee.handle_dest, &fee_ciphertext.destination_handle,
&ciphertext_fee.handle_withdraw_withheld_authority, &fee_ciphertext.withdraw_withheld_authority_handle,
), ),
transcript, transcript,
)?; )?;
let commitment_claimed_negated = &(*COMMITMENT_MAX_FEE_BASIS_POINTS) - &commitment_claimed; let claimed_commitment_negated = &(*COMMITMENT_MAX_FEE_BASIS_POINTS) - &claimed_commitment;
range_proof.verify( range_proof.verify(
vec![ vec![
&commitment_new_source, &new_source_commitment,
&ciphertext_lo.commitment, &ciphertext_lo.commitment,
&ciphertext_hi.commitment, &ciphertext_hi.commitment,
&commitment_claimed, &claimed_commitment,
&commitment_claimed_negated, &claimed_commitment_negated,
], ],
vec![64, 32, 32, 64, 64], vec![64, 32, 32, 64, 64],
transcript, transcript,
@ -517,42 +524,43 @@ impl TransferWithFeeProof {
#[repr(C)] #[repr(C)]
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
pub struct TransferWithFeePubkeys { pub struct TransferWithFeePubkeys {
pub pubkey_source: ElGamalPubkey, pub source_pubkey: ElGamalPubkey,
pub pubkey_dest: ElGamalPubkey, pub destination_pubkey: ElGamalPubkey,
pub pubkey_auditor: ElGamalPubkey, pub auditor_pubkey: ElGamalPubkey,
pub pubkey_withdraw_withheld_authority: ElGamalPubkey, pub withdraw_withheld_authority_pubkey: ElGamalPubkey,
} }
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
impl TransferWithFeePubkeys { impl TransferWithFeePubkeys {
pub fn to_bytes(&self) -> [u8; 128] { pub fn to_bytes(&self) -> [u8; 128] {
let mut bytes = [0u8; 128]; let mut bytes = [0u8; 128];
bytes[..32].copy_from_slice(&self.pubkey_source.to_bytes()); bytes[..32].copy_from_slice(&self.source_pubkey.to_bytes());
bytes[32..64].copy_from_slice(&self.pubkey_dest.to_bytes()); bytes[32..64].copy_from_slice(&self.destination_pubkey.to_bytes());
bytes[64..96].copy_from_slice(&self.pubkey_auditor.to_bytes()); bytes[64..96].copy_from_slice(&self.auditor_pubkey.to_bytes());
bytes[96..128].copy_from_slice(&self.pubkey_withdraw_withheld_authority.to_bytes()); bytes[96..128].copy_from_slice(&self.withdraw_withheld_authority_pubkey.to_bytes());
bytes bytes
} }
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ProofError> { pub fn from_bytes(bytes: &[u8]) -> Result<Self, ProofError> {
let bytes = array_ref![bytes, 0, 128]; let bytes = array_ref![bytes, 0, 128];
let (pubkey_source, pubkey_dest, pubkey_auditor, pubkey_withdraw_withheld_authority) = let (source_pubkey, destination_pubkey, auditor_pubkey, withdraw_withheld_authority_pubkey) =
array_refs![bytes, 32, 32, 32, 32]; array_refs![bytes, 32, 32, 32, 32];
let pubkey_source = let source_pubkey =
ElGamalPubkey::from_bytes(pubkey_source).ok_or(ProofError::Verification)?; ElGamalPubkey::from_bytes(source_pubkey).ok_or(ProofError::Verification)?;
let pubkey_dest = ElGamalPubkey::from_bytes(pubkey_dest).ok_or(ProofError::Verification)?; let destination_pubkey =
let pubkey_auditor = ElGamalPubkey::from_bytes(destination_pubkey).ok_or(ProofError::Verification)?;
ElGamalPubkey::from_bytes(pubkey_auditor).ok_or(ProofError::Verification)?; let auditor_pubkey =
let pubkey_withdraw_withheld_authority = ElGamalPubkey::from_bytes(auditor_pubkey).ok_or(ProofError::Verification)?;
ElGamalPubkey::from_bytes(pubkey_withdraw_withheld_authority) let withdraw_withheld_authority_pubkey =
ElGamalPubkey::from_bytes(withdraw_withheld_authority_pubkey)
.ok_or(ProofError::Verification)?; .ok_or(ProofError::Verification)?;
Ok(Self { Ok(Self {
pubkey_source, source_pubkey,
pubkey_dest, destination_pubkey,
pubkey_auditor, auditor_pubkey,
pubkey_withdraw_withheld_authority, withdraw_withheld_authority_pubkey,
}) })
} }
} }
@ -562,22 +570,23 @@ impl TransferWithFeePubkeys {
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
pub struct FeeEncryption { pub struct FeeEncryption {
pub commitment: PedersenCommitment, pub commitment: PedersenCommitment,
pub handle_dest: DecryptHandle, pub destination_handle: DecryptHandle,
pub handle_withdraw_withheld_authority: DecryptHandle, pub withdraw_withheld_authority_handle: DecryptHandle,
} }
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
impl FeeEncryption { impl FeeEncryption {
pub fn new( pub fn new(
amount: u64, amount: u64,
pubkey_dest: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey,
pubkey_withdraw_withheld: &ElGamalPubkey, withdraw_withheld_authority_pubkey: &ElGamalPubkey,
) -> (Self, PedersenOpening) { ) -> (Self, PedersenOpening) {
let (commitment, opening) = Pedersen::new(amount); let (commitment, opening) = Pedersen::new(amount);
let fee_encryption = Self { let fee_encryption = Self {
commitment, commitment,
handle_dest: pubkey_dest.decrypt_handle(&opening), destination_handle: destination_pubkey.decrypt_handle(&opening),
handle_withdraw_withheld_authority: pubkey_withdraw_withheld.decrypt_handle(&opening), withdraw_withheld_authority_handle: withdraw_withheld_authority_pubkey
.decrypt_handle(&opening),
}; };
(fee_encryption, opening) (fee_encryption, opening)
@ -586,8 +595,8 @@ impl FeeEncryption {
pub fn to_pod(&self) -> pod::FeeEncryption { pub fn to_pod(&self) -> pod::FeeEncryption {
pod::FeeEncryption { pod::FeeEncryption {
commitment: self.commitment.into(), commitment: self.commitment.into(),
handle_dest: self.handle_dest.into(), destination_handle: self.destination_handle.into(),
handle_withdraw_withheld_authority: self.handle_withdraw_withheld_authority.into(), withdraw_withheld_authority_handle: self.withdraw_withheld_authority_handle.into(),
} }
} }
} }
@ -640,30 +649,30 @@ fn calculate_fee(transfer_amount: u64, fee_rate_basis_points: u16) -> (u64, u64)
fn compute_delta_commitment_and_opening( fn compute_delta_commitment_and_opening(
(commitment_lo, opening_lo): (&PedersenCommitment, &PedersenOpening), (commitment_lo, opening_lo): (&PedersenCommitment, &PedersenOpening),
(commitment_hi, opening_hi): (&PedersenCommitment, &PedersenOpening), (commitment_hi, opening_hi): (&PedersenCommitment, &PedersenOpening),
(commitment_fee, opening_fee): (&PedersenCommitment, &PedersenOpening), (fee_commitment, opening_fee): (&PedersenCommitment, &PedersenOpening),
fee_rate_basis_points: u16, fee_rate_basis_points: u16,
) -> (PedersenCommitment, PedersenOpening) { ) -> (PedersenCommitment, PedersenOpening) {
let fee_rate_scalar = Scalar::from(fee_rate_basis_points); let fee_rate_scalar = Scalar::from(fee_rate_basis_points);
let commitment_delta = commitment_fee * Scalar::from(MAX_FEE_BASIS_POINTS) let delta_commitment = fee_commitment * Scalar::from(MAX_FEE_BASIS_POINTS)
- &(&combine_u32_commitments(commitment_lo, commitment_hi) * &fee_rate_scalar); - &(&combine_u32_commitments(commitment_lo, commitment_hi) * &fee_rate_scalar);
let opening_delta = opening_fee * Scalar::from(MAX_FEE_BASIS_POINTS) let opening_delta = opening_fee * Scalar::from(MAX_FEE_BASIS_POINTS)
- &(&combine_u32_openings(opening_lo, opening_hi) * &fee_rate_scalar); - &(&combine_u32_openings(opening_lo, opening_hi) * &fee_rate_scalar);
(commitment_delta, opening_delta) (delta_commitment, opening_delta)
} }
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
fn compute_delta_commitment( fn compute_delta_commitment(
commitment_lo: &PedersenCommitment, commitment_lo: &PedersenCommitment,
commitment_hi: &PedersenCommitment, commitment_hi: &PedersenCommitment,
commitment_fee: &PedersenCommitment, fee_commitment: &PedersenCommitment,
fee_rate_basis_points: u16, fee_rate_basis_points: u16,
) -> PedersenCommitment { ) -> PedersenCommitment {
let fee_rate_scalar = Scalar::from(fee_rate_basis_points); let fee_rate_scalar = Scalar::from(fee_rate_basis_points);
commitment_fee * Scalar::from(MAX_FEE_BASIS_POINTS) fee_commitment * Scalar::from(MAX_FEE_BASIS_POINTS)
- &(&combine_u32_commitments(commitment_lo, commitment_hi) * &fee_rate_scalar) - &(&combine_u32_commitments(commitment_lo, commitment_hi) * &fee_rate_scalar)
} }
@ -673,28 +682,28 @@ mod test {
#[test] #[test]
fn test_fee_correctness() { fn test_fee_correctness() {
let keypair_source = ElGamalKeypair::new_rand(); let source_keypair = ElGamalKeypair::new_rand();
let pubkey_dest = ElGamalKeypair::new_rand().public; let destination_pubkey = ElGamalKeypair::new_rand().public;
let pubkey_auditor = ElGamalKeypair::new_rand().public; let auditor_pubkey = ElGamalKeypair::new_rand().public;
let pubkey_withdraw_withheld_authority = ElGamalKeypair::new_rand().public; let withdraw_withheld_authority_pubkey = ElGamalKeypair::new_rand().public;
let spendable_balance: u64 = 120; let spendable_balance: u64 = 120;
let spendable_ciphertext = keypair_source.public.encrypt(spendable_balance); let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
let transfer_amount: u64 = 100; let transfer_amount: u64 = 100;
let fee_parameters = FeeParameters { let fee_parameters = FeeParameters {
fee_rate_basis_points: 100, fee_rate_basis_points: 400,
maximum_fee: 3, maximum_fee: 3,
}; };
let fee_data = TransferWithFeeData::new( let fee_data = TransferWithFeeData::new(
transfer_amount, transfer_amount,
(spendable_balance, &spendable_ciphertext), (spendable_balance, &spendable_ciphertext),
&keypair_source, &source_keypair,
(&pubkey_dest, &pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
fee_parameters, fee_parameters,
&pubkey_withdraw_withheld_authority, &withdraw_withheld_authority_pubkey,
) )
.unwrap(); .unwrap();

View File

@ -28,13 +28,13 @@ use {
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)] #[repr(C)]
pub struct WithdrawWithheldTokensData { pub struct WithdrawWithheldTokensData {
pub pubkey_withdraw_withheld_authority: pod::ElGamalPubkey, pub withdraw_withheld_authority_pubkey: pod::ElGamalPubkey,
pub pubkey_dest: pod::ElGamalPubkey, pub destination_pubkey: pod::ElGamalPubkey,
pub ciphertext_withdraw_withheld_authority: pod::ElGamalCiphertext, pub withdraw_withheld_authority_ciphertext: pod::ElGamalCiphertext,
pub ciphertext_dest: pod::ElGamalCiphertext, pub destination_ciphertext: pod::ElGamalCiphertext,
pub proof: WithdrawWithheldTokensProof, pub proof: WithdrawWithheldTokensProof,
} }
@ -42,42 +42,42 @@ pub struct WithdrawWithheldTokensData {
impl WithdrawWithheldTokensData { impl WithdrawWithheldTokensData {
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
pub fn new( pub fn new(
keypair_withdraw_withheld_authority: &ElGamalKeypair, withdraw_withheld_authority_keypair: &ElGamalKeypair,
pubkey_dest: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey,
ciphertext_withdraw_withheld_authority: &ElGamalCiphertext, withdraw_withheld_authority_ciphertext: &ElGamalCiphertext,
amount: u64, amount: u64,
) -> Result<Self, ProofError> { ) -> Result<Self, ProofError> {
let opening_dest = PedersenOpening::new_rand(); let destination_opening = PedersenOpening::new_rand();
let ciphertext_dest = pubkey_dest.encrypt_with(amount, &opening_dest); let destination_ciphertext = destination_pubkey.encrypt_with(amount, &destination_opening);
let pod_pubkey_withdraw_withheld_authority = let pod_withdraw_withheld_authority_pubkey =
pod::ElGamalPubkey(keypair_withdraw_withheld_authority.public.to_bytes()); pod::ElGamalPubkey(withdraw_withheld_authority_keypair.public.to_bytes());
let pod_pubkey_dest = pod::ElGamalPubkey(pubkey_dest.to_bytes()); let pod_destination_pubkey = pod::ElGamalPubkey(destination_pubkey.to_bytes());
let pod_ciphertext_withdraw_withheld_authority = let pod_withdraw_withheld_authority_ciphertext =
pod::ElGamalCiphertext(ciphertext_withdraw_withheld_authority.to_bytes()); pod::ElGamalCiphertext(withdraw_withheld_authority_ciphertext.to_bytes());
let pod_ciphertext_dest = pod::ElGamalCiphertext(ciphertext_dest.to_bytes()); let pod_destination_ciphertext = pod::ElGamalCiphertext(destination_ciphertext.to_bytes());
let mut transcript = WithdrawWithheldTokensProof::transcript_new( let mut transcript = WithdrawWithheldTokensProof::transcript_new(
&pod_pubkey_withdraw_withheld_authority, &pod_withdraw_withheld_authority_pubkey,
&pod_pubkey_dest, &pod_destination_pubkey,
&pod_ciphertext_withdraw_withheld_authority, &pod_withdraw_withheld_authority_ciphertext,
&pod_ciphertext_dest, &pod_destination_ciphertext,
); );
let proof = WithdrawWithheldTokensProof::new( let proof = WithdrawWithheldTokensProof::new(
keypair_withdraw_withheld_authority, withdraw_withheld_authority_keypair,
pubkey_dest, destination_pubkey,
ciphertext_withdraw_withheld_authority, withdraw_withheld_authority_ciphertext,
amount, amount,
&opening_dest, &destination_opening,
&mut transcript, &mut transcript,
); );
Ok(Self { Ok(Self {
pubkey_withdraw_withheld_authority: pod_pubkey_withdraw_withheld_authority, withdraw_withheld_authority_pubkey: pod_withdraw_withheld_authority_pubkey,
pubkey_dest: pod_pubkey_dest, destination_pubkey: pod_destination_pubkey,
ciphertext_withdraw_withheld_authority: pod_ciphertext_withdraw_withheld_authority, withdraw_withheld_authority_ciphertext: pod_withdraw_withheld_authority_ciphertext,
ciphertext_dest: pod_ciphertext_dest, destination_ciphertext: pod_destination_ciphertext,
proof, proof,
}) })
} }
@ -87,24 +87,24 @@ impl WithdrawWithheldTokensData {
impl Verifiable for WithdrawWithheldTokensData { impl Verifiable for WithdrawWithheldTokensData {
fn verify(&self) -> Result<(), ProofError> { fn verify(&self) -> Result<(), ProofError> {
let mut transcript = WithdrawWithheldTokensProof::transcript_new( let mut transcript = WithdrawWithheldTokensProof::transcript_new(
&self.pubkey_withdraw_withheld_authority, &self.withdraw_withheld_authority_pubkey,
&self.pubkey_dest, &self.destination_pubkey,
&self.ciphertext_withdraw_withheld_authority, &self.withdraw_withheld_authority_ciphertext,
&self.ciphertext_dest, &self.destination_ciphertext,
); );
let pubkey_withdraw_withheld_authority = let withdraw_withheld_authority_pubkey =
self.pubkey_withdraw_withheld_authority.try_into()?; self.withdraw_withheld_authority_pubkey.try_into()?;
let pubkey_dest = self.pubkey_dest.try_into()?; let destination_pubkey = self.destination_pubkey.try_into()?;
let ciphertext_withdraw_withheld_authority = let withdraw_withheld_authority_ciphertext =
self.ciphertext_withdraw_withheld_authority.try_into()?; self.withdraw_withheld_authority_ciphertext.try_into()?;
let ciphertext_dest = self.ciphertext_dest.try_into()?; let destination_ciphertext = self.destination_ciphertext.try_into()?;
self.proof.verify( self.proof.verify(
&pubkey_withdraw_withheld_authority, &withdraw_withheld_authority_pubkey,
&pubkey_dest, &destination_pubkey,
&ciphertext_withdraw_withheld_authority, &withdraw_withheld_authority_ciphertext,
&ciphertext_dest, &destination_ciphertext,
&mut transcript, &mut transcript,
) )
} }
@ -123,42 +123,42 @@ pub struct WithdrawWithheldTokensProof {
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
impl WithdrawWithheldTokensProof { impl WithdrawWithheldTokensProof {
fn transcript_new( fn transcript_new(
pubkey_withdraw_withheld_authority: &pod::ElGamalPubkey, withdraw_withheld_authority_pubkey: &pod::ElGamalPubkey,
pubkey_dest: &pod::ElGamalPubkey, destination_pubkey: &pod::ElGamalPubkey,
ciphertext_withdraw_withheld_authority: &pod::ElGamalCiphertext, withdraw_withheld_authority_ciphertext: &pod::ElGamalCiphertext,
ciphertext_dest: &pod::ElGamalCiphertext, destination_ciphertext: &pod::ElGamalCiphertext,
) -> Transcript { ) -> Transcript {
let mut transcript = Transcript::new(b"WithdrawWithheldTokensProof"); let mut transcript = Transcript::new(b"WithdrawWithheldTokensProof");
transcript.append_pubkey( transcript.append_pubkey(
b"withdraw-withheld-authority-pubkey", b"withdraw-withheld-authority-pubkey",
pubkey_withdraw_withheld_authority, withdraw_withheld_authority_pubkey,
); );
transcript.append_pubkey(b"dest-pubkey", pubkey_dest); transcript.append_pubkey(b"dest-pubkey", destination_pubkey);
transcript.append_ciphertext( transcript.append_ciphertext(
b"ciphertext-withdraw-withheld-authority", b"ciphertext-withdraw-withheld-authority",
ciphertext_withdraw_withheld_authority, withdraw_withheld_authority_ciphertext,
); );
transcript.append_ciphertext(b"ciphertext-dest", ciphertext_dest); transcript.append_ciphertext(b"ciphertext-dest", destination_ciphertext);
transcript transcript
} }
pub fn new( pub fn new(
keypair_withdraw_withheld_authority: &ElGamalKeypair, withdraw_withheld_authority_keypair: &ElGamalKeypair,
pubkey_dest: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey,
ciphertext_withdraw_withheld_authority: &ElGamalCiphertext, withdraw_withheld_authority_ciphertext: &ElGamalCiphertext,
amount: u64, amount: u64,
opening_dest: &PedersenOpening, destination_opening: &PedersenOpening,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Self { ) -> Self {
let equality_proof = CtxtCtxtEqualityProof::new( let equality_proof = CtxtCtxtEqualityProof::new(
keypair_withdraw_withheld_authority, withdraw_withheld_authority_keypair,
pubkey_dest, destination_pubkey,
ciphertext_withdraw_withheld_authority, withdraw_withheld_authority_ciphertext,
amount, amount,
opening_dest, destination_opening,
transcript, transcript,
); );
@ -169,18 +169,18 @@ impl WithdrawWithheldTokensProof {
pub fn verify( pub fn verify(
&self, &self,
pubkey_source: &ElGamalPubkey, source_pubkey: &ElGamalPubkey,
pubkey_dest: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey,
ciphertext_source: &ElGamalCiphertext, source_ciphertext: &ElGamalCiphertext,
ciphertext_dest: &ElGamalCiphertext, destination_ciphertext: &ElGamalCiphertext,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), ProofError> { ) -> Result<(), ProofError> {
let proof: CtxtCtxtEqualityProof = self.proof.try_into()?; let proof: CtxtCtxtEqualityProof = self.proof.try_into()?;
proof.verify( proof.verify(
pubkey_source, source_pubkey,
pubkey_dest, destination_pubkey,
ciphertext_source, source_ciphertext,
ciphertext_dest, destination_ciphertext,
transcript, transcript,
)?; )?;
@ -194,17 +194,17 @@ mod test {
#[test] #[test]
fn test_close_account_correctness() { fn test_close_account_correctness() {
let keypair_withdraw_withheld_authority = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_keypair = ElGamalKeypair::new_rand();
let keypair_dest = ElGamalKeypair::new_rand(); let dest_keypair = ElGamalKeypair::new_rand();
let amount: u64 = 55; let amount: u64 = 55;
let ciphertext_withdraw_withheld_authority = let withdraw_withheld_authority_ciphertext =
keypair_withdraw_withheld_authority.public.encrypt(amount); withdraw_withheld_authority_keypair.public.encrypt(amount);
let withdraw_withheld_tokens_data = WithdrawWithheldTokensData::new( let withdraw_withheld_tokens_data = WithdrawWithheldTokensData::new(
&keypair_withdraw_withheld_authority, &withdraw_withheld_authority_keypair,
&keypair_dest.public, &dest_keypair.public,
&ciphertext_withdraw_withheld_authority, &withdraw_withheld_authority_ciphertext,
amount, amount,
) )
.unwrap(); .unwrap();

View File

@ -59,14 +59,14 @@ impl CtxtCommEqualityProof {
/// Note that the proof constructor does not take the actual Pedersen commitment as input; it /// Note that the proof constructor does not take the actual Pedersen commitment as input; it
/// takes the associated Pedersen opening instead. /// takes the associated Pedersen opening instead.
/// ///
/// * `elgamal_keypair` - The ElGamal keypair associated with the ciphertext to be proved /// * `source_keypair` - The ElGamal keypair associated with the first to be proved
/// * `ciphertext` - The main ElGamal ciphertext to be proved /// * `source_ciphertext` - The main ElGamal ciphertext to be proved
/// * `amount` - The message associated with the ElGamal ciphertext and Pedersen commitment /// * `amount` - The message associated with the ElGamal ciphertext and Pedersen commitment
/// * `opening` - The opening associated with the main Pedersen commitment to be proved /// * `opening` - The opening associated with the main Pedersen commitment to be proved
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn new( pub fn new(
keypair_source: &ElGamalKeypair, source_keypair: &ElGamalKeypair,
ciphertext_source: &ElGamalCiphertext, source_ciphertext: &ElGamalCiphertext,
amount: u64, amount: u64,
opening: &PedersenOpening, opening: &PedersenOpening,
transcript: &mut Transcript, transcript: &mut Transcript,
@ -74,10 +74,10 @@ impl CtxtCommEqualityProof {
transcript.equality_proof_domain_sep(); transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs // extract the relevant scalar and Ristretto points from the inputs
let P_source = keypair_source.public.get_point(); let P_source = source_keypair.public.get_point();
let D_source = ciphertext_source.handle.get_point(); let D_source = source_ciphertext.handle.get_point();
let s = keypair_source.secret.get_scalar(); let s = source_keypair.secret.get_scalar();
let x = Scalar::from(amount); let x = Scalar::from(amount);
let r = opening.get_scalar(); let r = opening.get_scalar();
@ -121,24 +121,24 @@ impl CtxtCommEqualityProof {
/// Equality proof verifier. TODO: wrt commitment /// Equality proof verifier. TODO: wrt commitment
/// ///
/// * `elgamal_pubkey` - The ElGamal pubkey associated with the ciphertext to be proved /// * `source_pubkey` - The ElGamal pubkey associated with the ciphertext to be proved
/// * `ciphertext` - The main ElGamal ciphertext to be proved /// * `source_ciphertext` - The main ElGamal ciphertext to be proved
/// * `commitment` - The main Pedersen commitment to be proved /// * `destination_commitment` - The main Pedersen commitment to be proved
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn verify( pub fn verify(
self, self,
pubkey_source: &ElGamalPubkey, source_pubkey: &ElGamalPubkey,
ciphertext_source: &ElGamalCiphertext, source_ciphertext: &ElGamalCiphertext,
commitment_dest: &PedersenCommitment, destination_commitment: &PedersenCommitment,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), EqualityProofError> { ) -> Result<(), EqualityProofError> {
transcript.equality_proof_domain_sep(); transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs // extract the relevant scalar and Ristretto points from the inputs
let P_source = pubkey_source.get_point(); let P_source = source_pubkey.get_point();
let C_source = ciphertext_source.commitment.get_point(); let C_source = source_ciphertext.commitment.get_point();
let D_source = ciphertext_source.handle.get_point(); let D_source = source_ciphertext.handle.get_point();
let C_dest = commitment_dest.get_point(); let C_destination = destination_commitment.get_point();
// include Y_0, Y_1, Y_2 to transcript and extract challenges // include Y_0, Y_1, Y_2 to transcript and extract challenges
transcript.validate_and_append_point(b"Y_0", &self.Y_0)?; transcript.validate_and_append_point(b"Y_0", &self.Y_0)?;
@ -181,7 +181,7 @@ impl CtxtCommEqualityProof {
&Y_1, // Y_1 &Y_1, // Y_1
&(*G), // G &(*G), // G
&(*H), // H &(*H), // H
C_dest, // C_dest C_destination, // C_destination
&Y_2, // Y_2 &Y_2, // Y_2
], ],
); );
@ -256,29 +256,30 @@ impl CtxtCtxtEqualityProof {
/// Note that the proof constructor does not take the actual Pedersen commitment as input; it /// Note that the proof constructor does not take the actual Pedersen commitment as input; it
/// takes the associated Pedersen opening instead. /// takes the associated Pedersen opening instead.
/// ///
/// * `elgamal_keypair` - The ElGamal keypair associated with the ciphertext to be proved /// * `source_keypair` - The ElGamal keypair associated with the first ciphertext to be proved
/// * `ciphertext` - The main ElGamal ciphertext to be proved /// * `destination_pubkey` - The ElGamal pubkey associated with the second ElGamal ciphertext
/// * `source_ciphertext` - The first ElGamal ciphertext
/// * `amount` - The message associated with the ElGamal ciphertext and Pedersen commitment /// * `amount` - The message associated with the ElGamal ciphertext and Pedersen commitment
/// * `opening` - The opening associated with the main Pedersen commitment to be proved /// * `destination_opening` - The opening associated with the second ElGamal ciphertext
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn new( pub fn new(
keypair_source: &ElGamalKeypair, source_keypair: &ElGamalKeypair,
pubkey_dest: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey,
ciphertext_source: &ElGamalCiphertext, source_ciphertext: &ElGamalCiphertext,
amount: u64, amount: u64,
opening_dest: &PedersenOpening, destination_opening: &PedersenOpening,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Self { ) -> Self {
transcript.equality_proof_domain_sep(); transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs // extract the relevant scalar and Ristretto points from the inputs
let P_source = keypair_source.public.get_point(); let P_source = source_keypair.public.get_point();
let D_source = ciphertext_source.handle.get_point(); let D_source = source_ciphertext.handle.get_point();
let P_dest = pubkey_dest.get_point(); let P_destination = destination_pubkey.get_point();
let s = keypair_source.secret.get_scalar(); let s = source_keypair.secret.get_scalar();
let x = Scalar::from(amount); let x = Scalar::from(amount);
let r = opening_dest.get_scalar(); let r = destination_opening.get_scalar();
// generate random masking factors that also serves as nonces // generate random masking factors that also serves as nonces
let mut y_s = Scalar::random(&mut OsRng); let mut y_s = Scalar::random(&mut OsRng);
@ -289,7 +290,7 @@ impl CtxtCtxtEqualityProof {
let Y_1 = let Y_1 =
RistrettoPoint::multiscalar_mul(vec![&y_x, &y_s], vec![&(*G), D_source]).compress(); RistrettoPoint::multiscalar_mul(vec![&y_x, &y_s], vec![&(*G), D_source]).compress();
let Y_2 = RistrettoPoint::multiscalar_mul(vec![&y_x, &y_r], vec![&(*G), &(*H)]).compress(); let Y_2 = RistrettoPoint::multiscalar_mul(vec![&y_x, &y_r], vec![&(*G), &(*H)]).compress();
let Y_3 = (&y_r * P_dest).compress(); let Y_3 = (&y_r * P_destination).compress();
// record masking factors in the transcript // record masking factors in the transcript
transcript.append_point(b"Y_0", &Y_0); transcript.append_point(b"Y_0", &Y_0);
@ -321,30 +322,31 @@ impl CtxtCtxtEqualityProof {
} }
} }
/// Equality proof verifier. TODO: wrt commitment /// Equality proof verifier.
/// ///
/// * `elgamal_pubkey` - The ElGamal pubkey associated with the ciphertext to be proved /// * `source_pubkey` - The ElGamal pubkey associated with the first ciphertext to be proved
/// * `ciphertext` - The main ElGamal ciphertext to be proved /// * `destination_pubkey` - The ElGamal pubkey associated with the second ciphertext to be proved
/// * `commitment` - The main Pedersen commitment to be proved /// * `source_ciphertext` - The first ElGamal ciphertext to be proved
/// * `destination_ciphertext` - The second ElGamal ciphertext to be proved
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn verify( pub fn verify(
self, self,
pubkey_source: &ElGamalPubkey, source_pubkey: &ElGamalPubkey,
pubkey_dest: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey,
ciphertext_source: &ElGamalCiphertext, source_ciphertext: &ElGamalCiphertext,
ciphertext_dest: &ElGamalCiphertext, destination_ciphertext: &ElGamalCiphertext,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), EqualityProofError> { ) -> Result<(), EqualityProofError> {
transcript.equality_proof_domain_sep(); transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs // extract the relevant scalar and Ristretto points from the inputs
let P_source = pubkey_source.get_point(); let P_source = source_pubkey.get_point();
let C_source = ciphertext_source.commitment.get_point(); let C_source = source_ciphertext.commitment.get_point();
let D_source = ciphertext_source.handle.get_point(); let D_source = source_ciphertext.handle.get_point();
let P_dest = pubkey_dest.get_point(); let P_destination = destination_pubkey.get_point();
let C_dest = ciphertext_dest.commitment.get_point(); let C_destination = destination_ciphertext.commitment.get_point();
let D_dest = ciphertext_dest.handle.get_point(); let D_destination = destination_ciphertext.handle.get_point();
// include Y_0, Y_1, Y_2 to transcript and extract challenges // include Y_0, Y_1, Y_2 to transcript and extract challenges
transcript.validate_and_append_point(b"Y_0", &self.Y_0)?; transcript.validate_and_append_point(b"Y_0", &self.Y_0)?;
@ -394,10 +396,10 @@ impl CtxtCtxtEqualityProof {
&Y_1, // Y_1 &Y_1, // Y_1
&(*G), // G &(*G), // G
&(*H), // H &(*H), // H
C_dest, // C_dest C_destination, // C_destination
&Y_2, // Y_2 &Y_2, // Y_2
P_dest, // P_dest P_destination, // P_destination
D_dest, // D_dest D_destination, // D_destination
&Y_3, // Y_3 &Y_3, // Y_3
], ],
); );
@ -456,57 +458,57 @@ mod test {
#[test] #[test]
fn test_ciphertext_commitment_equality_proof_correctness() { fn test_ciphertext_commitment_equality_proof_correctness() {
// success case // success case
let keypair_source = ElGamalKeypair::new_rand(); let source_keypair = ElGamalKeypair::new_rand();
let message: u64 = 55; let message: u64 = 55;
let ciphertext_source = keypair_source.public.encrypt(message); let source_ciphertext = source_keypair.public.encrypt(message);
let (commitment_dest, opening_dest) = Pedersen::new(message); let (destination_commitment, destination_opening) = Pedersen::new(message);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new( let proof = CtxtCommEqualityProof::new(
&keypair_source, &source_keypair,
&ciphertext_source, &source_ciphertext,
message, message,
&opening_dest, &destination_opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&keypair_source.public, &source_keypair.public,
&ciphertext_source, &source_ciphertext,
&commitment_dest, &destination_commitment,
&mut transcript_verifier &mut verifier_transcript
) )
.is_ok()); .is_ok());
// fail case: encrypted and committed messages are different // fail case: encrypted and committed messages are different
let keypair_source = ElGamalKeypair::new_rand(); let source_keypair = ElGamalKeypair::new_rand();
let encrypted_message: u64 = 55; let encrypted_message: u64 = 55;
let committed_message: u64 = 77; let committed_message: u64 = 77;
let ciphertext_source = keypair_source.public.encrypt(encrypted_message); let source_ciphertext = source_keypair.public.encrypt(encrypted_message);
let (commitment_dest, opening_dest) = Pedersen::new(committed_message); let (destination_commitment, destination_opening) = Pedersen::new(committed_message);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new( let proof = CtxtCommEqualityProof::new(
&keypair_source, &source_keypair,
&ciphertext_source, &source_ciphertext,
message, message,
&opening_dest, &destination_opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&keypair_source.public, &source_keypair.public,
&ciphertext_source, &source_ciphertext,
&commitment_dest, &destination_commitment,
&mut transcript_verifier &mut verifier_transcript
) )
.is_err()); .is_err());
} }
@ -523,15 +525,15 @@ mod test {
let ciphertext = elgamal_keypair.public.encrypt(message); let ciphertext = elgamal_keypair.public.encrypt(message);
let (commitment, opening) = Pedersen::new(message); let (commitment, opening) = Pedersen::new(message);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new( let proof = CtxtCommEqualityProof::new(
&elgamal_keypair, &elgamal_keypair,
&ciphertext, &ciphertext,
message, message,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
@ -539,7 +541,7 @@ mod test {
&elgamal_keypair.public, &elgamal_keypair.public,
&ciphertext, &ciphertext,
&commitment, &commitment,
&mut transcript_verifier &mut verifier_transcript
) )
.is_err()); .is_err());
@ -552,15 +554,15 @@ mod test {
let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap(); let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap();
let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap(); let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap();
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new( let proof = CtxtCommEqualityProof::new(
&elgamal_keypair, &elgamal_keypair,
&ciphertext, &ciphertext,
message, message,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
@ -568,7 +570,7 @@ mod test {
&elgamal_keypair.public, &elgamal_keypair.public,
&ciphertext, &ciphertext,
&commitment, &commitment,
&mut transcript_verifier &mut verifier_transcript
) )
.is_ok()); .is_ok());
@ -581,15 +583,15 @@ mod test {
let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap(); let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap();
let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap(); let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap();
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new( let proof = CtxtCommEqualityProof::new(
&elgamal_keypair, &elgamal_keypair,
&ciphertext, &ciphertext,
message, message,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
@ -597,7 +599,7 @@ mod test {
&elgamal_keypair.public, &elgamal_keypair.public,
&ciphertext, &ciphertext,
&commitment, &commitment,
&mut transcript_verifier &mut verifier_transcript
) )
.is_ok()); .is_ok());
@ -609,15 +611,15 @@ mod test {
let ciphertext = ElGamalCiphertext::from_bytes(&[0u8; 64]).unwrap(); let ciphertext = ElGamalCiphertext::from_bytes(&[0u8; 64]).unwrap();
let (commitment, opening) = Pedersen::new(message); let (commitment, opening) = Pedersen::new(message);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new( let proof = CtxtCommEqualityProof::new(
&elgamal_keypair, &elgamal_keypair,
&ciphertext, &ciphertext,
message, message,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
@ -625,7 +627,7 @@ mod test {
&elgamal_keypair.public, &elgamal_keypair.public,
&ciphertext, &ciphertext,
&commitment, &commitment,
&mut transcript_verifier &mut verifier_transcript
) )
.is_ok()); .is_ok());
} }
@ -633,67 +635,69 @@ mod test {
#[test] #[test]
fn test_ciphertext_ciphertext_equality_proof_correctness() { fn test_ciphertext_ciphertext_equality_proof_correctness() {
// success case // success case
let keypair_source = ElGamalKeypair::new_rand(); let source_keypair = ElGamalKeypair::new_rand();
let keypair_dest = ElGamalKeypair::new_rand(); let destination_keypair = ElGamalKeypair::new_rand();
let message: u64 = 55; let message: u64 = 55;
let ciphertext_source = keypair_source.public.encrypt(message); let source_ciphertext = source_keypair.public.encrypt(message);
let opening_dest = PedersenOpening::new_rand(); let destination_opening = PedersenOpening::new_rand();
let ciphertext_dest = keypair_dest.public.encrypt_with(message, &opening_dest); let destination_ciphertext = destination_keypair
.public
.encrypt_with(message, &destination_opening);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCtxtEqualityProof::new( let proof = CtxtCtxtEqualityProof::new(
&keypair_source, &source_keypair,
&keypair_dest.public, &destination_keypair.public,
&ciphertext_source, &source_ciphertext,
message, message,
&opening_dest, &destination_opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&keypair_source.public, &source_keypair.public,
&keypair_dest.public, &destination_keypair.public,
&ciphertext_source, &source_ciphertext,
&ciphertext_dest, &destination_ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_ok()); .is_ok());
// fail case: encrypted and committed messages are different // fail case: encrypted and committed messages are different
let message_source: u64 = 55; let source_message: u64 = 55;
let message_dest: u64 = 77; let destination_message: u64 = 77;
let ciphertext_source = keypair_source.public.encrypt(message_source); let source_ciphertext = source_keypair.public.encrypt(source_message);
let opening_dest = PedersenOpening::new_rand(); let destination_opening = PedersenOpening::new_rand();
let ciphertext_dest = keypair_dest let destination_ciphertext = destination_keypair
.public .public
.encrypt_with(message_dest, &opening_dest); .encrypt_with(destination_message, &destination_opening);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCtxtEqualityProof::new( let proof = CtxtCtxtEqualityProof::new(
&keypair_source, &source_keypair,
&keypair_dest.public, &destination_keypair.public,
&ciphertext_source, &source_ciphertext,
message, message,
&opening_dest, &destination_opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&keypair_source.public, &source_keypair.public,
&keypair_dest.public, &destination_keypair.public,
&ciphertext_source, &source_ciphertext,
&ciphertext_dest, &destination_ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_err()); .is_err());
} }

View File

@ -40,18 +40,18 @@ impl FeeSigmaProof {
/// Creates a fee sigma proof assuming that the committed fee is greater than the maximum fee /// Creates a fee sigma proof assuming that the committed fee is greater than the maximum fee
/// bound. /// bound.
/// ///
/// * `(fee_amount, commitment_fee, opening_fee)` - The amount, Pedersen commitment, and /// * `(fee_amount, fee_commitment, fee_opening)` - The amount, Pedersen commitment, and
/// opening of the transfer fee /// opening of the transfer fee
/// * `(delta_fee, commitment_delta, opening_delta)` - The amount, Pedersen commitment, and /// * `(delta_fee, delta_commitment, delta_opening)` - The amount, Pedersen commitment, and
/// opening of the "real" delta amount /// opening of the "real" delta amount
/// * `(commitment_claimed, opening_claimed)` - The Pedersen commitment and opening of the /// * `(claimed_commitment, claimed_opening)` - The Pedersen commitment and opening of the
/// "claimed" delta amount /// "claimed" delta amount
/// * `max_fee` - The maximum fee bound /// * `max_fee` - The maximum fee bound
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn new( pub fn new(
(fee_amount, commitment_fee, opening_fee): (u64, &PedersenCommitment, &PedersenOpening), (fee_amount, fee_commitment, fee_opening): (u64, &PedersenCommitment, &PedersenOpening),
(delta_fee, commitment_delta, opening_delta): (u64, &PedersenCommitment, &PedersenOpening), (delta_fee, delta_commitment, delta_opening): (u64, &PedersenCommitment, &PedersenOpening),
(commitment_claimed, opening_claimed): (&PedersenCommitment, &PedersenOpening), (claimed_commitment, claimed_opening): (&PedersenCommitment, &PedersenOpening),
max_fee: u64, max_fee: u64,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Self { ) -> Self {
@ -60,16 +60,16 @@ impl FeeSigmaProof {
// compute proof for both cases `fee_amount' >= `max_fee` and `fee_amount` < `max_fee` // compute proof for both cases `fee_amount' >= `max_fee` and `fee_amount` < `max_fee`
let proof_fee_above_max = Self::create_proof_fee_above_max( let proof_fee_above_max = Self::create_proof_fee_above_max(
opening_fee, fee_opening,
commitment_delta, delta_commitment,
commitment_claimed, claimed_commitment,
&mut transcript_fee_above_max, &mut transcript_fee_above_max,
); );
let proof_fee_below_max = Self::create_proof_fee_below_max( let proof_fee_below_max = Self::create_proof_fee_below_max(
commitment_fee, fee_commitment,
(delta_fee, opening_delta), (delta_fee, delta_opening),
opening_claimed, claimed_opening,
max_fee, max_fee,
&mut transcript_fee_below_max, &mut transcript_fee_below_max,
); );
@ -100,19 +100,19 @@ impl FeeSigmaProof {
/// Creates a fee sigma proof assuming that the committed fee is greater than the maximum fee /// Creates a fee sigma proof assuming that the committed fee is greater than the maximum fee
/// bound. /// bound.
/// ///
/// * `opening_fee` - The opening of the Pedersen commitment of the transfer fee /// * `fee_opening` - The opening of the Pedersen commitment of the transfer fee
/// * `commitment_delta` - The Pedersen commitment of the "real" delta value /// * `delta_commitment` - The Pedersen commitment of the "real" delta value
/// * `commitment_claimed` - The Pedersen commitment of the "claimed" delta value /// * `claimed_commitment` - The Pedersen commitment of the "claimed" delta value
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
fn create_proof_fee_above_max( fn create_proof_fee_above_max(
opening_fee: &PedersenOpening, fee_opening: &PedersenOpening,
commitment_delta: &PedersenCommitment, delta_commitment: &PedersenCommitment,
commitment_claimed: &PedersenCommitment, claimed_commitment: &PedersenCommitment,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Self { ) -> Self {
// simulate equality proof // simulate equality proof
let C_delta = commitment_delta.get_point(); let C_delta = delta_commitment.get_point();
let C_claimed = commitment_claimed.get_point(); let C_claimed = claimed_commitment.get_point();
let z_x = Scalar::random(&mut OsRng); let z_x = Scalar::random(&mut OsRng);
let z_delta = Scalar::random(&mut OsRng); let z_delta = Scalar::random(&mut OsRng);
@ -140,7 +140,7 @@ impl FeeSigmaProof {
}; };
// generate max proof // generate max proof
let r_fee = opening_fee.get_scalar(); let r_fee = fee_opening.get_scalar();
let y_max_proof = Scalar::random(&mut OsRng); let y_max_proof = Scalar::random(&mut OsRng);
let Y_max_proof = (y_max_proof * &(*H)).compress(); let Y_max_proof = (y_max_proof * &(*H)).compress();
@ -171,22 +171,22 @@ impl FeeSigmaProof {
/// Creates a fee sigma proof assuming that the committed fee is less than the maximum fee /// Creates a fee sigma proof assuming that the committed fee is less than the maximum fee
/// bound. /// bound.
/// ///
/// * `commitment_fee` - The Pedersen commitment of the transfer fee /// * `fee_commitment` - The Pedersen commitment of the transfer fee
/// * `(delta_fee, opening_delta)` - The Pedersen commitment and opening of the "real" delta /// * `(delta_fee, delta_opening)` - The Pedersen commitment and opening of the "real" delta
/// value /// value
/// * `opening_claimed` - The opening of the Pedersen commitment of the "claimed" delta value /// * `claimed_opening` - The opening of the Pedersen commitment of the "claimed" delta value
/// * `max_fee` - The maximum fee bound /// * `max_fee` - The maximum fee bound
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
fn create_proof_fee_below_max( fn create_proof_fee_below_max(
commitment_fee: &PedersenCommitment, fee_commitment: &PedersenCommitment,
(delta_fee, opening_delta): (u64, &PedersenOpening), (delta_fee, delta_opening): (u64, &PedersenOpening),
opening_claimed: &PedersenOpening, claimed_opening: &PedersenOpening,
max_fee: u64, max_fee: u64,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Self { ) -> Self {
// simulate max proof // simulate max proof
let m = Scalar::from(max_fee); let m = Scalar::from(max_fee);
let C_fee = commitment_fee.get_point(); let C_fee = fee_commitment.get_point();
let z_max_proof = Scalar::random(&mut OsRng); let z_max_proof = Scalar::random(&mut OsRng);
let c_max_proof = Scalar::random(&mut OsRng); // random challenge let c_max_proof = Scalar::random(&mut OsRng); // random challenge
@ -207,8 +207,8 @@ impl FeeSigmaProof {
// generate equality proof // generate equality proof
let x = Scalar::from(delta_fee); let x = Scalar::from(delta_fee);
let r_delta = opening_delta.get_scalar(); let r_delta = delta_opening.get_scalar();
let r_claimed = opening_claimed.get_scalar(); let r_claimed = claimed_opening.get_scalar();
let y_x = Scalar::random(&mut OsRng); let y_x = Scalar::random(&mut OsRng);
let y_delta = Scalar::random(&mut OsRng); let y_delta = Scalar::random(&mut OsRng);
@ -248,25 +248,25 @@ impl FeeSigmaProof {
/// Fee sigma proof verifier. /// Fee sigma proof verifier.
/// ///
/// * `commitment_fee` - The Pedersen commitment of the transfer fee /// * `fee_commitment` - The Pedersen commitment of the transfer fee
/// * `commitment_delta` - The Pedersen commitment of the "real" delta value /// * `delta_commitment` - The Pedersen commitment of the "real" delta value
/// * `commitment_claimed` - The Pedersen commitment of the "claimed" delta value /// * `claimed_commitment` - The Pedersen commitment of the "claimed" delta value
/// * `max_fee` - The maximum fee bound /// * `max_fee` - The maximum fee bound
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn verify( pub fn verify(
self, self,
commitment_fee: &PedersenCommitment, fee_commitment: &PedersenCommitment,
commitment_delta: &PedersenCommitment, delta_commitment: &PedersenCommitment,
commitment_claimed: &PedersenCommitment, claimed_commitment: &PedersenCommitment,
max_fee: u64, max_fee: u64,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), FeeSigmaProofError> { ) -> Result<(), FeeSigmaProofError> {
// extract the relevant scalar and Ristretto points from the input // extract the relevant scalar and Ristretto points from the input
let m = Scalar::from(max_fee); let m = Scalar::from(max_fee);
let C_max = commitment_fee.get_point(); let C_max = fee_commitment.get_point();
let C_delta = commitment_delta.get_point(); let C_delta = delta_commitment.get_point();
let C_claimed = commitment_claimed.get_point(); let C_claimed = claimed_commitment.get_point();
transcript.validate_and_append_point(b"Y_max_proof", &self.fee_max_proof.Y_max_proof)?; transcript.validate_and_append_point(b"Y_max_proof", &self.fee_max_proof.Y_max_proof)?;
transcript.validate_and_append_point(b"Y_delta", &self.fee_equality_proof.Y_delta)?; transcript.validate_and_append_point(b"Y_delta", &self.fee_equality_proof.Y_delta)?;
@ -455,39 +455,39 @@ mod test {
let transfer_amount: u64 = 55; let transfer_amount: u64 = 55;
let max_fee: u64 = 3; let max_fee: u64 = 3;
let rate_fee: u16 = 555; // 5.55% let fee_rate: u16 = 555; // 5.55%
let amount_fee: u64 = 4; let fee_amount: u64 = 4;
let delta: u64 = 9475; // 4*10000 - 55*555 let delta: u64 = 9475; // 4*10000 - 55*555
let (commitment_transfer, opening_transfer) = Pedersen::new(transfer_amount); let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
let (commitment_fee, opening_fee) = Pedersen::new(max_fee); let (fee_commitment, fee_opening) = Pedersen::new(max_fee);
let scalar_rate = Scalar::from(rate_fee); let scalar_rate = Scalar::from(fee_rate);
let commitment_delta = let delta_commitment =
&commitment_fee * &Scalar::from(10000_u64) - &commitment_transfer * &scalar_rate; &fee_commitment * &Scalar::from(10000_u64) - &transfer_commitment * &scalar_rate;
let opening_delta = let delta_opening =
&opening_fee * &Scalar::from(10000_u64) - &opening_transfer * &scalar_rate; &fee_opening * &Scalar::from(10000_u64) - &transfer_opening * &scalar_rate;
let (commitment_claimed, opening_claimed) = Pedersen::new(0_u64); let (claimed_commitment, claimed_opening) = Pedersen::new(0_u64);
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
let proof = FeeSigmaProof::new( let proof = FeeSigmaProof::new(
(amount_fee, &commitment_fee, &opening_fee), (fee_amount, &fee_commitment, &fee_opening),
(delta, &commitment_delta, &opening_delta), (delta, &delta_commitment, &delta_opening),
(&commitment_claimed, &opening_claimed), (&claimed_commitment, &claimed_opening),
max_fee, max_fee,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment_fee, &fee_commitment,
&commitment_delta, &delta_commitment,
&commitment_claimed, &claimed_commitment,
max_fee, max_fee,
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_ok()); .is_ok());
} }
@ -497,44 +497,44 @@ mod test {
let transfer_amount: u64 = 55; let transfer_amount: u64 = 55;
let max_fee: u64 = 77; let max_fee: u64 = 77;
let rate_fee: u16 = 555; // 5.55% let fee_rate: u16 = 555; // 5.55%
let amount_fee: u64 = 4; let fee_amount: u64 = 4;
let delta: u64 = 9475; // 4*10000 - 55*555 let delta: u64 = 9475; // 4*10000 - 55*555
let (commitment_transfer, opening_transfer) = Pedersen::new(transfer_amount); let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
let (commitment_fee, opening_fee) = Pedersen::new(amount_fee); let (fee_commitment, fee_opening) = Pedersen::new(fee_amount);
let scalar_rate = Scalar::from(rate_fee); let scalar_rate = Scalar::from(fee_rate);
let commitment_delta = let delta_commitment =
&commitment_fee * &Scalar::from(10000_u64) - &commitment_transfer * &scalar_rate; &fee_commitment * &Scalar::from(10000_u64) - &transfer_commitment * &scalar_rate;
let opening_delta = let delta_opening =
&opening_fee * &Scalar::from(10000_u64) - &opening_transfer * &scalar_rate; &fee_opening * &Scalar::from(10000_u64) - &transfer_opening * &scalar_rate;
let (commitment_claimed, opening_claimed) = Pedersen::new(delta); let (claimed_commitment, claimed_opening) = Pedersen::new(delta);
assert_eq!( assert_eq!(
commitment_delta.get_point() - opening_delta.get_scalar() * &(*H), delta_commitment.get_point() - delta_opening.get_scalar() * &(*H),
commitment_claimed.get_point() - opening_claimed.get_scalar() * &(*H) claimed_commitment.get_point() - claimed_opening.get_scalar() * &(*H)
); );
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
let proof = FeeSigmaProof::new( let proof = FeeSigmaProof::new(
(amount_fee, &commitment_fee, &opening_fee), (fee_amount, &fee_commitment, &fee_opening),
(delta, &commitment_delta, &opening_delta), (delta, &delta_commitment, &delta_opening),
(&commitment_claimed, &opening_claimed), (&claimed_commitment, &claimed_opening),
max_fee, max_fee,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment_fee, &fee_commitment,
&commitment_delta, &delta_commitment,
&commitment_claimed, &claimed_commitment,
max_fee, max_fee,
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_ok()); .is_ok());
} }
@ -544,39 +544,39 @@ mod test {
let transfer_amount: u64 = 100; let transfer_amount: u64 = 100;
let max_fee: u64 = 3; let max_fee: u64 = 3;
let rate_fee: u16 = 100; // 1.00% let fee_rate: u16 = 100; // 1.00%
let amount_fee: u64 = 1; let fee_amount: u64 = 1;
let delta: u64 = 0; // 1*10000 - 100*100 let delta: u64 = 0; // 1*10000 - 100*100
let (commitment_transfer, opening_transfer) = Pedersen::new(transfer_amount); let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
let (commitment_fee, opening_fee) = Pedersen::new(amount_fee); let (fee_commitment, fee_opening) = Pedersen::new(fee_amount);
let scalar_rate = Scalar::from(rate_fee); let scalar_rate = Scalar::from(fee_rate);
let commitment_delta = let delta_commitment =
&(&commitment_fee * &Scalar::from(10000_u64)) - &(&commitment_transfer * &scalar_rate); &(&fee_commitment * &Scalar::from(10000_u64)) - &(&transfer_commitment * &scalar_rate);
let opening_delta = let delta_opening =
&(&opening_fee * &Scalar::from(10000_u64)) - &(&opening_transfer * &scalar_rate); &(&fee_opening * &Scalar::from(10000_u64)) - &(&transfer_opening * &scalar_rate);
let (commitment_claimed, opening_claimed) = Pedersen::new(delta); let (claimed_commitment, claimed_opening) = Pedersen::new(delta);
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
let proof = FeeSigmaProof::new( let proof = FeeSigmaProof::new(
(amount_fee, &commitment_fee, &opening_fee), (fee_amount, &fee_commitment, &fee_opening),
(delta, &commitment_delta, &opening_delta), (delta, &delta_commitment, &delta_opening),
(&commitment_claimed, &opening_claimed), (&claimed_commitment, &claimed_opening),
max_fee, max_fee,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment_fee, &fee_commitment,
&commitment_delta, &delta_commitment,
&commitment_claimed, &claimed_commitment,
max_fee, max_fee,
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_ok()); .is_ok());
} }

View File

@ -56,13 +56,13 @@ impl ValidityProof {
/// Note that the proof constructor does not take the actual Pedersen commitment or decryption /// Note that the proof constructor does not take the actual Pedersen commitment or decryption
/// handles as input; it only takes the associated Pedersen opening instead. /// handles as input; it only takes the associated Pedersen opening instead.
/// ///
/// * `(pubkey_dest, pubkey_auditor)` - The ElGamal public keys associated with the decryption /// * `(destination_pubkey, auditor_pubkey)` - The ElGamal public keys associated with the decryption
/// handles /// handles
/// * `amount` - The committed message in the commitment /// * `amount` - The committed message in the commitment
/// * `opening` - The opening associated with the Pedersen commitment /// * `opening` - The opening associated with the Pedersen commitment
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn new<T: Into<Scalar>>( pub fn new<T: Into<Scalar>>(
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), // TODO: rename pubkey_auditor (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), // TODO: rename auditor_pubkey
amount: T, amount: T,
opening: &PedersenOpening, opening: &PedersenOpening,
transcript: &mut Transcript, transcript: &mut Transcript,
@ -70,8 +70,8 @@ impl ValidityProof {
transcript.validity_proof_domain_sep(); transcript.validity_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs // extract the relevant scalar and Ristretto points from the inputs
let P_dest = pubkey_dest.get_point(); let P_dest = destination_pubkey.get_point();
let P_auditor = pubkey_auditor.get_point(); let P_auditor = auditor_pubkey.get_point();
let x = amount.into(); let x = amount.into();
let r = opening.get_scalar(); let r = opening.get_scalar();
@ -111,15 +111,15 @@ impl ValidityProof {
/// The ciphertext validity proof verifier. /// The ciphertext validity proof verifier.
/// ///
/// * `commitment` - The Pedersen commitment /// * `commitment` - The Pedersen commitment
/// * `(pubkey_dest, pubkey_auditor)` - The ElGamal pubkeys associated with the decryption /// * `(destination_pubkey, auditor_pubkey)` - The ElGamal pubkeys associated with the decryption
/// handles /// handles
/// * `(handle_dest, handle_audtior)` - The decryption handles /// * `(destination_handle, auditor_handle)` - The decryption handles
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic /// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn verify( pub fn verify(
self, self,
commitment: &PedersenCommitment, commitment: &PedersenCommitment,
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
(handle_dest, handle_auditor): (&DecryptHandle, &DecryptHandle), (destination_handle, auditor_handle): (&DecryptHandle, &DecryptHandle),
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), ValidityProofError> { ) -> Result<(), ValidityProofError> {
transcript.validity_proof_domain_sep(); transcript.validity_proof_domain_sep();
@ -141,12 +141,12 @@ impl ValidityProof {
let Y_1 = self.Y_1.decompress().ok_or(ValidityProofError::Format)?; let Y_1 = self.Y_1.decompress().ok_or(ValidityProofError::Format)?;
let Y_2 = self.Y_2.decompress().ok_or(ValidityProofError::Format)?; let Y_2 = self.Y_2.decompress().ok_or(ValidityProofError::Format)?;
let P_dest = pubkey_dest.get_point(); let P_dest = destination_pubkey.get_point();
let P_auditor = pubkey_auditor.get_point(); let P_auditor = auditor_pubkey.get_point();
let C = commitment.get_point(); let C = commitment.get_point();
let D_dest = handle_dest.get_point(); let D_dest = destination_handle.get_point();
let D_auditor = handle_auditor.get_point(); let D_auditor = auditor_handle.get_point();
let check = RistrettoPoint::vartime_multiscalar_mul( let check = RistrettoPoint::vartime_multiscalar_mul(
vec![ vec![
@ -217,9 +217,9 @@ impl ValidityProof {
/// ///
/// An aggregated ciphertext validity proof certifies the validity of two instances of a standard /// An aggregated ciphertext validity proof certifies the validity of two instances of a standard
/// ciphertext validity proof. An instance of a standard validity proof consist of one ciphertext /// ciphertext validity proof. An instance of a standard validity proof consist of one ciphertext
/// and two decryption handles `(commitment, handle_dest, handle_auditor)`. An instance of an /// and two decryption handles `(commitment, destination_handle, auditor_handle)`. An instance of an
/// aggregated ciphertext validity proof is a pair `(commitment_0, handle_dest_0, /// aggregated ciphertext validity proof is a pair `(commitment_0, destination_handle_0,
/// handle_auditor_0)` and `(commitment_1, handle_dest_1, handle_auditor_1)`. The proof certifies /// auditor_handle_0)` and `(commitment_1, destination_handle_1, auditor_handle_1)`. The proof certifies
/// the analogous decryptable properties for each one of these pair of commitment and decryption /// the analogous decryptable properties for each one of these pair of commitment and decryption
/// handles. /// handles.
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -234,7 +234,7 @@ impl AggregatedValidityProof {
/// The function simples aggregates the input openings and invokes the standard ciphertext /// The function simples aggregates the input openings and invokes the standard ciphertext
/// validity proof constructor. /// validity proof constructor.
pub fn new<T: Into<Scalar>>( pub fn new<T: Into<Scalar>>(
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
(amount_lo, amount_hi): (T, T), (amount_lo, amount_hi): (T, T),
(opening_lo, opening_hi): (&PedersenOpening, &PedersenOpening), (opening_lo, opening_hi): (&PedersenOpening, &PedersenOpening),
transcript: &mut Transcript, transcript: &mut Transcript,
@ -247,7 +247,7 @@ impl AggregatedValidityProof {
let aggregated_opening = opening_lo + &(opening_hi * &t); let aggregated_opening = opening_lo + &(opening_hi * &t);
AggregatedValidityProof(ValidityProof::new( AggregatedValidityProof(ValidityProof::new(
(pubkey_dest, pubkey_auditor), (destination_pubkey, auditor_pubkey),
aggregated_message, aggregated_message,
&aggregated_opening, &aggregated_opening,
transcript, transcript,
@ -263,10 +263,10 @@ impl AggregatedValidityProof {
/// This function is randomized. It uses `OsRng` internally to generate random scalars. /// This function is randomized. It uses `OsRng` internally to generate random scalars.
pub fn verify( pub fn verify(
self, self,
(pubkey_dest, pubkey_auditor): (&ElGamalPubkey, &ElGamalPubkey), (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
(commitment_lo, commitment_hi): (&PedersenCommitment, &PedersenCommitment), (commitment_lo, commitment_hi): (&PedersenCommitment, &PedersenCommitment),
(handle_lo_dest, handle_hi_dest): (&DecryptHandle, &DecryptHandle), (destination_handle_lo, destination_handle_hi): (&DecryptHandle, &DecryptHandle),
(handle_lo_auditor, handle_hi_auditor): (&DecryptHandle, &DecryptHandle), (auditor_handle_lo, auditor_handle_hi): (&DecryptHandle, &DecryptHandle),
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), ValidityProofError> { ) -> Result<(), ValidityProofError> {
transcript.aggregated_validity_proof_domain_sep(); transcript.aggregated_validity_proof_domain_sep();
@ -274,15 +274,15 @@ impl AggregatedValidityProof {
let t = transcript.challenge_scalar(b"t"); let t = transcript.challenge_scalar(b"t");
let aggregated_commitment = commitment_lo + commitment_hi * t; let aggregated_commitment = commitment_lo + commitment_hi * t;
let aggregated_handle_dest = handle_lo_dest + handle_hi_dest * t; let destination_aggregated_handle = destination_handle_lo + destination_handle_hi * t;
let aggregated_handle_auditor = handle_lo_auditor + handle_hi_auditor * t; let auditor_aggregated_handle = auditor_handle_lo + auditor_handle_hi * t;
let AggregatedValidityProof(validity_proof) = self; let AggregatedValidityProof(validity_proof) = self;
validity_proof.verify( validity_proof.verify(
&aggregated_commitment, &aggregated_commitment,
(pubkey_dest, pubkey_auditor), (destination_pubkey, auditor_pubkey),
(&aggregated_handle_dest, &aggregated_handle_auditor), (&destination_aggregated_handle, &auditor_aggregated_handle),
transcript, transcript,
) )
} }
@ -305,31 +305,31 @@ mod test {
#[test] #[test]
fn test_validity_proof_correctness() { fn test_validity_proof_correctness() {
let elgamal_pubkey_dest = ElGamalKeypair::new_rand().public; let destination_pubkey = ElGamalKeypair::new_rand().public;
let elgamal_pubkey_auditor = ElGamalKeypair::new_rand().public; let auditor_pubkey = ElGamalKeypair::new_rand().public;
let amount: u64 = 55; let amount: u64 = 55;
let (commitment, opening) = Pedersen::new(amount); let (commitment, opening) = Pedersen::new(amount);
let handle_dest = elgamal_pubkey_dest.decrypt_handle(&opening); let destination_handle = destination_pubkey.decrypt_handle(&opening);
let handle_auditor = elgamal_pubkey_auditor.decrypt_handle(&opening); let auditor_handle = auditor_pubkey.decrypt_handle(&opening);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = ValidityProof::new( let proof = ValidityProof::new(
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
amount, amount,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment, &commitment,
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
(&handle_dest, &handle_auditor), (&destination_handle, &auditor_handle),
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_ok()); .is_ok());
} }
@ -337,127 +337,127 @@ mod test {
#[test] #[test]
fn test_validity_proof_edge_cases() { fn test_validity_proof_edge_cases() {
// if destination public key zeroed, then the proof should always reject // if destination public key zeroed, then the proof should always reject
let elgamal_pubkey_dest = ElGamalPubkey::from_bytes(&[0u8; 32]).unwrap(); let destination_pubkey = ElGamalPubkey::from_bytes(&[0u8; 32]).unwrap();
let elgamal_pubkey_auditor = ElGamalKeypair::new_rand().public; let auditor_pubkey = ElGamalKeypair::new_rand().public;
let amount: u64 = 55; let amount: u64 = 55;
let (commitment, opening) = Pedersen::new(amount); let (commitment, opening) = Pedersen::new(amount);
let handle_dest = elgamal_pubkey_dest.decrypt_handle(&opening); let destination_handle = destination_pubkey.decrypt_handle(&opening);
let handle_auditor = elgamal_pubkey_auditor.decrypt_handle(&opening); let auditor_handle = auditor_pubkey.decrypt_handle(&opening);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = ValidityProof::new( let proof = ValidityProof::new(
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
amount, amount,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment, &commitment,
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
(&handle_dest, &handle_auditor), (&destination_handle, &auditor_handle),
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_err()); .is_err());
// if auditor public key zeroed, then the proof should always reject // if auditor public key zeroed, then the proof should always reject
let elgamal_pubkey_dest = ElGamalKeypair::new_rand().public; let destination_pubkey = ElGamalKeypair::new_rand().public;
let elgamal_pubkey_auditor = ElGamalPubkey::from_bytes(&[0u8; 32]).unwrap(); let auditor_pubkey = ElGamalPubkey::from_bytes(&[0u8; 32]).unwrap();
let amount: u64 = 55; let amount: u64 = 55;
let (commitment, opening) = Pedersen::new(amount); let (commitment, opening) = Pedersen::new(amount);
let handle_dest = elgamal_pubkey_dest.decrypt_handle(&opening); let destination_handle = destination_pubkey.decrypt_handle(&opening);
let handle_auditor = elgamal_pubkey_auditor.decrypt_handle(&opening); let auditor_handle = auditor_pubkey.decrypt_handle(&opening);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = ValidityProof::new( let proof = ValidityProof::new(
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
amount, amount,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment, &commitment,
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
(&handle_dest, &handle_auditor), (&destination_handle, &auditor_handle),
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_err()); .is_err());
// all zeroed ciphertext should still be valid // all zeroed ciphertext should still be valid
let elgamal_pubkey_dest = ElGamalKeypair::new_rand().public; let destination_pubkey = ElGamalKeypair::new_rand().public;
let elgamal_pubkey_auditor = ElGamalKeypair::new_rand().public; let auditor_pubkey = ElGamalKeypair::new_rand().public;
let amount: u64 = 0; let amount: u64 = 0;
let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap(); let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap();
let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap(); let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap();
let handle_dest = elgamal_pubkey_dest.decrypt_handle(&opening); let destination_handle = destination_pubkey.decrypt_handle(&opening);
let handle_auditor = elgamal_pubkey_auditor.decrypt_handle(&opening); let auditor_handle = auditor_pubkey.decrypt_handle(&opening);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = ValidityProof::new( let proof = ValidityProof::new(
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
amount, amount,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment, &commitment,
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
(&handle_dest, &handle_auditor), (&destination_handle, &auditor_handle),
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_ok()); .is_ok());
// decryption handles can be zero as long as the Pedersen commitment is valid // decryption handles can be zero as long as the Pedersen commitment is valid
let elgamal_pubkey_dest = ElGamalKeypair::new_rand().public; let destination_pubkey = ElGamalKeypair::new_rand().public;
let elgamal_pubkey_auditor = ElGamalKeypair::new_rand().public; let auditor_pubkey = ElGamalKeypair::new_rand().public;
let amount: u64 = 55; let amount: u64 = 55;
let (commitment, opening) = Pedersen::new(amount); let (commitment, opening) = Pedersen::new(amount);
let handle_dest = elgamal_pubkey_dest.decrypt_handle(&opening); let destination_handle = destination_pubkey.decrypt_handle(&opening);
let handle_auditor = elgamal_pubkey_auditor.decrypt_handle(&opening); let auditor_handle = auditor_pubkey.decrypt_handle(&opening);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = ValidityProof::new( let proof = ValidityProof::new(
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
amount, amount,
&opening, &opening,
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
&commitment, &commitment,
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
(&handle_dest, &handle_auditor), (&destination_handle, &auditor_handle),
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_ok()); .is_ok());
} }
#[test] #[test]
fn test_aggregated_validity_proof() { fn test_aggregated_validity_proof() {
let elgamal_pubkey_dest = ElGamalKeypair::new_rand().public; let destination_pubkey = ElGamalKeypair::new_rand().public;
let elgamal_pubkey_auditor = ElGamalKeypair::new_rand().public; let auditor_pubkey = ElGamalKeypair::new_rand().public;
let amount_lo: u64 = 55; let amount_lo: u64 = 55;
let amount_hi: u64 = 77; let amount_hi: u64 = 77;
@ -465,29 +465,29 @@ mod test {
let (commitment_lo, open_lo) = Pedersen::new(amount_lo); let (commitment_lo, open_lo) = Pedersen::new(amount_lo);
let (commitment_hi, open_hi) = Pedersen::new(amount_hi); let (commitment_hi, open_hi) = Pedersen::new(amount_hi);
let handle_lo_dest = elgamal_pubkey_dest.decrypt_handle(&open_lo); let destination_handle_lo = destination_pubkey.decrypt_handle(&open_lo);
let handle_hi_dest = elgamal_pubkey_dest.decrypt_handle(&open_hi); let destination_handle_hi = destination_pubkey.decrypt_handle(&open_hi);
let handle_lo_auditor = elgamal_pubkey_auditor.decrypt_handle(&open_lo); let auditor_handle_lo = auditor_pubkey.decrypt_handle(&open_lo);
let handle_hi_auditor = elgamal_pubkey_auditor.decrypt_handle(&open_hi); let auditor_handle_hi = auditor_pubkey.decrypt_handle(&open_hi);
let mut transcript_prover = Transcript::new(b"Test"); let mut prover_transcript = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test");
let proof = AggregatedValidityProof::new( let proof = AggregatedValidityProof::new(
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
(amount_lo, amount_hi), (amount_lo, amount_hi),
(&open_lo, &open_hi), (&open_lo, &open_hi),
&mut transcript_prover, &mut prover_transcript,
); );
assert!(proof assert!(proof
.verify( .verify(
(&elgamal_pubkey_dest, &elgamal_pubkey_auditor), (&destination_pubkey, &auditor_pubkey),
(&commitment_lo, &commitment_hi), (&commitment_lo, &commitment_hi),
(&handle_lo_dest, &handle_hi_dest), (&destination_handle_lo, &destination_handle_hi),
(&handle_lo_auditor, &handle_hi_auditor), (&auditor_handle_lo, &auditor_handle_hi),
&mut transcript_verifier, &mut verifier_transcript,
) )
.is_ok()); .is_ok());
} }

View File

@ -178,30 +178,30 @@ mod test {
fn test_zero_balance_proof_correctness() { fn test_zero_balance_proof_correctness() {
let source_keypair = ElGamalKeypair::new_rand(); let source_keypair = ElGamalKeypair::new_rand();
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
// general case: encryption of 0 // general case: encryption of 0
let elgamal_ciphertext = source_keypair.public.encrypt(0_u64); let elgamal_ciphertext = source_keypair.public.encrypt(0_u64);
let proof = let proof =
ZeroBalanceProof::new(&source_keypair, &elgamal_ciphertext, &mut transcript_prover); ZeroBalanceProof::new(&source_keypair, &elgamal_ciphertext, &mut prover_transcript);
assert!(proof assert!(proof
.verify( .verify(
&source_keypair.public, &source_keypair.public,
&elgamal_ciphertext, &elgamal_ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_ok()); .is_ok());
// general case: encryption of > 0 // general case: encryption of > 0
let elgamal_ciphertext = source_keypair.public.encrypt(1_u64); let elgamal_ciphertext = source_keypair.public.encrypt(1_u64);
let proof = let proof =
ZeroBalanceProof::new(&source_keypair, &elgamal_ciphertext, &mut transcript_prover); ZeroBalanceProof::new(&source_keypair, &elgamal_ciphertext, &mut prover_transcript);
assert!(proof assert!(proof
.verify( .verify(
&source_keypair.public, &source_keypair.public,
&elgamal_ciphertext, &elgamal_ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_err()); .is_err());
} }
@ -210,26 +210,26 @@ mod test {
fn test_zero_balance_proof_edge_cases() { fn test_zero_balance_proof_edge_cases() {
let source_keypair = ElGamalKeypair::new_rand(); let source_keypair = ElGamalKeypair::new_rand();
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
// all zero ciphertext should always be a valid encryption of 0 // all zero ciphertext should always be a valid encryption of 0
let ciphertext = ElGamalCiphertext::from_bytes(&[0u8; 64]).unwrap(); let ciphertext = ElGamalCiphertext::from_bytes(&[0u8; 64]).unwrap();
let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut transcript_prover); let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut prover_transcript);
assert!(proof assert!(proof
.verify( .verify(
&source_keypair.public, &source_keypair.public,
&ciphertext, &ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_ok()); .is_ok());
// if only either commitment or handle is zero, the ciphertext is always invalid and proof // if only either commitment or handle is zero, the ciphertext is always invalid and proof
// verification should always reject // verification should always reject
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
let zeroed_commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap(); let zeroed_commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap();
let handle = source_keypair let handle = source_keypair
@ -241,18 +241,18 @@ mod test {
handle, handle,
}; };
let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut transcript_prover); let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut prover_transcript);
assert!(proof assert!(proof
.verify( .verify(
&source_keypair.public, &source_keypair.public,
&ciphertext, &ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_err()); .is_err());
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
let (zeroed_commitment, _) = Pedersen::new(0_u64); let (zeroed_commitment, _) = Pedersen::new(0_u64);
let ciphertext = ElGamalCiphertext { let ciphertext = ElGamalCiphertext {
@ -260,19 +260,19 @@ mod test {
handle: DecryptHandle::from_bytes(&[0u8; 32]).unwrap(), handle: DecryptHandle::from_bytes(&[0u8; 32]).unwrap(),
}; };
let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut transcript_prover); let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut prover_transcript);
assert!(proof assert!(proof
.verify( .verify(
&source_keypair.public, &source_keypair.public,
&ciphertext, &ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_err()); .is_err());
// if public key is always zero, then the proof should always reject // if public key is always zero, then the proof should always reject
let mut transcript_prover = Transcript::new(b"test"); let mut prover_transcript = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test"); let mut verifier_transcript = Transcript::new(b"test");
let public = ElGamalPubkey::from_bytes(&[0u8; 32]).unwrap(); let public = ElGamalPubkey::from_bytes(&[0u8; 32]).unwrap();
let secret = ElGamalSecretKey::new_rand(); let secret = ElGamalSecretKey::new_rand();
@ -281,13 +281,13 @@ mod test {
let ciphertext = elgamal_keypair.public.encrypt(0_u64); let ciphertext = elgamal_keypair.public.encrypt(0_u64);
let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut transcript_prover); let proof = ZeroBalanceProof::new(&source_keypair, &ciphertext, &mut prover_transcript);
assert!(proof assert!(proof
.verify( .verify(
&source_keypair.public, &source_keypair.public,
&ciphertext, &ciphertext,
&mut transcript_verifier &mut verifier_transcript
) )
.is_err()); .is_err());
} }

View File

@ -327,9 +327,9 @@ mod target_arch {
impl From<TransferPubkeys> for pod::TransferPubkeys { impl From<TransferPubkeys> for pod::TransferPubkeys {
fn from(keys: TransferPubkeys) -> Self { fn from(keys: TransferPubkeys) -> Self {
Self { Self {
pubkey_source: keys.pubkey_source.into(), source_pubkey: keys.source_pubkey.into(),
pubkey_dest: keys.pubkey_dest.into(), destination_pubkey: keys.destination_pubkey.into(),
pubkey_auditor: keys.pubkey_auditor.into(), auditor_pubkey: keys.auditor_pubkey.into(),
} }
} }
} }
@ -339,9 +339,9 @@ mod target_arch {
fn try_from(pod: pod::TransferPubkeys) -> Result<Self, Self::Error> { fn try_from(pod: pod::TransferPubkeys) -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
pubkey_source: pod.pubkey_source.try_into()?, source_pubkey: pod.source_pubkey.try_into()?,
pubkey_dest: pod.pubkey_dest.try_into()?, destination_pubkey: pod.destination_pubkey.try_into()?,
pubkey_auditor: pod.pubkey_auditor.try_into()?, auditor_pubkey: pod.auditor_pubkey.try_into()?,
}) })
} }
} }
@ -349,10 +349,10 @@ mod target_arch {
impl From<TransferWithFeePubkeys> for pod::TransferWithFeePubkeys { impl From<TransferWithFeePubkeys> for pod::TransferWithFeePubkeys {
fn from(keys: TransferWithFeePubkeys) -> Self { fn from(keys: TransferWithFeePubkeys) -> Self {
Self { Self {
pubkey_source: keys.pubkey_source.into(), source_pubkey: keys.source_pubkey.into(),
pubkey_dest: keys.pubkey_dest.into(), destination_pubkey: keys.destination_pubkey.into(),
pubkey_auditor: keys.pubkey_auditor.into(), auditor_pubkey: keys.auditor_pubkey.into(),
pubkey_withdraw_withheld_authority: keys.pubkey_withdraw_withheld_authority.into(), withdraw_withheld_authority_pubkey: keys.withdraw_withheld_authority_pubkey.into(),
} }
} }
} }
@ -362,11 +362,11 @@ mod target_arch {
fn try_from(pod: pod::TransferWithFeePubkeys) -> Result<Self, Self::Error> { fn try_from(pod: pod::TransferWithFeePubkeys) -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
pubkey_source: pod.pubkey_source.try_into()?, source_pubkey: pod.source_pubkey.try_into()?,
pubkey_dest: pod.pubkey_dest.try_into()?, destination_pubkey: pod.destination_pubkey.try_into()?,
pubkey_auditor: pod.pubkey_auditor.try_into()?, auditor_pubkey: pod.auditor_pubkey.try_into()?,
pubkey_withdraw_withheld_authority: pod withdraw_withheld_authority_pubkey: pod
.pubkey_withdraw_withheld_authority .withdraw_withheld_authority_pubkey
.try_into()?, .try_into()?,
}) })
} }
@ -376,9 +376,9 @@ mod target_arch {
fn from(ciphertext: TransferAmountEncryption) -> Self { fn from(ciphertext: TransferAmountEncryption) -> Self {
Self { Self {
commitment: ciphertext.commitment.into(), commitment: ciphertext.commitment.into(),
handle_source: ciphertext.handle_source.into(), source_handle: ciphertext.source_handle.into(),
handle_dest: ciphertext.handle_dest.into(), destination_handle: ciphertext.destination_handle.into(),
handle_auditor: ciphertext.handle_auditor.into(), auditor_handle: ciphertext.auditor_handle.into(),
} }
} }
} }
@ -389,9 +389,9 @@ mod target_arch {
fn try_from(pod: pod::TransferAmountEncryption) -> Result<Self, Self::Error> { fn try_from(pod: pod::TransferAmountEncryption) -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
commitment: pod.commitment.try_into()?, commitment: pod.commitment.try_into()?,
handle_source: pod.handle_source.try_into()?, source_handle: pod.source_handle.try_into()?,
handle_dest: pod.handle_dest.try_into()?, destination_handle: pod.destination_handle.try_into()?,
handle_auditor: pod.handle_auditor.try_into()?, auditor_handle: pod.auditor_handle.try_into()?,
}) })
} }
} }
@ -400,9 +400,9 @@ mod target_arch {
fn from(ciphertext: FeeEncryption) -> Self { fn from(ciphertext: FeeEncryption) -> Self {
Self { Self {
commitment: ciphertext.commitment.into(), commitment: ciphertext.commitment.into(),
handle_dest: ciphertext.handle_dest.into(), destination_handle: ciphertext.destination_handle.into(),
handle_withdraw_withheld_authority: ciphertext withdraw_withheld_authority_handle: ciphertext
.handle_withdraw_withheld_authority .withdraw_withheld_authority_handle
.into(), .into(),
} }
} }
@ -414,9 +414,9 @@ mod target_arch {
fn try_from(pod: pod::FeeEncryption) -> Result<Self, Self::Error> { fn try_from(pod: pod::FeeEncryption) -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
commitment: pod.commitment.try_into()?, commitment: pod.commitment.try_into()?,
handle_dest: pod.handle_dest.try_into()?, destination_handle: pod.destination_handle.try_into()?,
handle_withdraw_withheld_authority: pod withdraw_withheld_authority_handle: pod
.handle_withdraw_withheld_authority .withdraw_withheld_authority_handle
.try_into()?, .try_into()?,
}) })
} }

View File

@ -194,35 +194,35 @@ impl Default for AeCiphertext {
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)] #[repr(C)]
pub struct TransferPubkeys { pub struct TransferPubkeys {
pub pubkey_source: ElGamalPubkey, pub source_pubkey: ElGamalPubkey,
pub pubkey_dest: ElGamalPubkey, pub destination_pubkey: ElGamalPubkey,
pub pubkey_auditor: ElGamalPubkey, pub auditor_pubkey: ElGamalPubkey,
} }
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)] #[repr(C)]
pub struct TransferWithFeePubkeys { pub struct TransferWithFeePubkeys {
pub pubkey_source: ElGamalPubkey, pub source_pubkey: ElGamalPubkey,
pub pubkey_dest: ElGamalPubkey, pub destination_pubkey: ElGamalPubkey,
pub pubkey_auditor: ElGamalPubkey, pub auditor_pubkey: ElGamalPubkey,
pub pubkey_withdraw_withheld_authority: ElGamalPubkey, pub withdraw_withheld_authority_pubkey: ElGamalPubkey,
} }
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)] #[repr(C)]
pub struct TransferAmountEncryption { pub struct TransferAmountEncryption {
pub commitment: PedersenCommitment, pub commitment: PedersenCommitment,
pub handle_source: DecryptHandle, pub source_handle: DecryptHandle,
pub handle_dest: DecryptHandle, pub destination_handle: DecryptHandle,
pub handle_auditor: DecryptHandle, pub auditor_handle: DecryptHandle,
} }
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)] #[repr(C)]
pub struct FeeEncryption { pub struct FeeEncryption {
pub commitment: PedersenCommitment, pub commitment: PedersenCommitment,
pub handle_dest: DecryptHandle, pub destination_handle: DecryptHandle,
pub handle_withdraw_withheld_authority: DecryptHandle, pub withdraw_withheld_authority_handle: DecryptHandle,
} }
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]