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

View File

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

View File

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

View File

@ -59,14 +59,14 @@ impl CtxtCommEqualityProof {
/// Note that the proof constructor does not take the actual Pedersen commitment as input; it
/// takes the associated Pedersen opening instead.
///
/// * `elgamal_keypair` - The ElGamal keypair associated with the ciphertext to be proved
/// * `ciphertext` - The main ElGamal ciphertext to be proved
/// * `source_keypair` - The ElGamal keypair associated with the first to be proved
/// * `source_ciphertext` - The main ElGamal ciphertext to be proved
/// * `amount` - The message associated with the ElGamal ciphertext and Pedersen commitment
/// * `opening` - The opening associated with the main Pedersen commitment to be proved
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn new(
keypair_source: &ElGamalKeypair,
ciphertext_source: &ElGamalCiphertext,
source_keypair: &ElGamalKeypair,
source_ciphertext: &ElGamalCiphertext,
amount: u64,
opening: &PedersenOpening,
transcript: &mut Transcript,
@ -74,10 +74,10 @@ impl CtxtCommEqualityProof {
transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs
let P_source = keypair_source.public.get_point();
let D_source = ciphertext_source.handle.get_point();
let P_source = source_keypair.public.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 r = opening.get_scalar();
@ -121,24 +121,24 @@ impl CtxtCommEqualityProof {
/// Equality proof verifier. TODO: wrt commitment
///
/// * `elgamal_pubkey` - The ElGamal pubkey associated with the ciphertext to be proved
/// * `ciphertext` - The main ElGamal ciphertext to be proved
/// * `commitment` - The main Pedersen commitment to be proved
/// * `source_pubkey` - The ElGamal pubkey associated with the ciphertext to be proved
/// * `source_ciphertext` - The main ElGamal ciphertext to be proved
/// * `destination_commitment` - The main Pedersen commitment to be proved
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn verify(
self,
pubkey_source: &ElGamalPubkey,
ciphertext_source: &ElGamalCiphertext,
commitment_dest: &PedersenCommitment,
source_pubkey: &ElGamalPubkey,
source_ciphertext: &ElGamalCiphertext,
destination_commitment: &PedersenCommitment,
transcript: &mut Transcript,
) -> Result<(), EqualityProofError> {
transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs
let P_source = pubkey_source.get_point();
let C_source = ciphertext_source.commitment.get_point();
let D_source = ciphertext_source.handle.get_point();
let C_dest = commitment_dest.get_point();
let P_source = source_pubkey.get_point();
let C_source = source_ciphertext.commitment.get_point();
let D_source = source_ciphertext.handle.get_point();
let C_destination = destination_commitment.get_point();
// include Y_0, Y_1, Y_2 to transcript and extract challenges
transcript.validate_and_append_point(b"Y_0", &self.Y_0)?;
@ -172,17 +172,17 @@ impl CtxtCommEqualityProof {
&ww_negated, // -ww
],
vec![
P_source, // P_source
&(*H), // H
&Y_0, // Y_0
&(*G), // G
D_source, // D_source
C_source, // C_source
&Y_1, // Y_1
&(*G), // G
&(*H), // H
C_dest, // C_dest
&Y_2, // Y_2
P_source, // P_source
&(*H), // H
&Y_0, // Y_0
&(*G), // G
D_source, // D_source
C_source, // C_source
&Y_1, // Y_1
&(*G), // G
&(*H), // H
C_destination, // C_destination
&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
/// takes the associated Pedersen opening instead.
///
/// * `elgamal_keypair` - The ElGamal keypair associated with the ciphertext to be proved
/// * `ciphertext` - The main ElGamal ciphertext to be proved
/// * `source_keypair` - The ElGamal keypair associated with the first 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
/// * `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
pub fn new(
keypair_source: &ElGamalKeypair,
pubkey_dest: &ElGamalPubkey,
ciphertext_source: &ElGamalCiphertext,
source_keypair: &ElGamalKeypair,
destination_pubkey: &ElGamalPubkey,
source_ciphertext: &ElGamalCiphertext,
amount: u64,
opening_dest: &PedersenOpening,
destination_opening: &PedersenOpening,
transcript: &mut Transcript,
) -> Self {
transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs
let P_source = keypair_source.public.get_point();
let D_source = ciphertext_source.handle.get_point();
let P_dest = pubkey_dest.get_point();
let P_source = source_keypair.public.get_point();
let D_source = source_ciphertext.handle.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 r = opening_dest.get_scalar();
let r = destination_opening.get_scalar();
// generate random masking factors that also serves as nonces
let mut y_s = Scalar::random(&mut OsRng);
@ -289,7 +290,7 @@ impl CtxtCtxtEqualityProof {
let Y_1 =
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_3 = (&y_r * P_dest).compress();
let Y_3 = (&y_r * P_destination).compress();
// record masking factors in the transcript
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
/// * `ciphertext` - The main ElGamal ciphertext to be proved
/// * `commitment` - The main Pedersen commitment to be proved
/// * `source_pubkey` - The ElGamal pubkey associated with the first ciphertext to be proved
/// * `destination_pubkey` - The ElGamal pubkey associated with the second ciphertext 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
pub fn verify(
self,
pubkey_source: &ElGamalPubkey,
pubkey_dest: &ElGamalPubkey,
ciphertext_source: &ElGamalCiphertext,
ciphertext_dest: &ElGamalCiphertext,
source_pubkey: &ElGamalPubkey,
destination_pubkey: &ElGamalPubkey,
source_ciphertext: &ElGamalCiphertext,
destination_ciphertext: &ElGamalCiphertext,
transcript: &mut Transcript,
) -> Result<(), EqualityProofError> {
transcript.equality_proof_domain_sep();
// extract the relevant scalar and Ristretto points from the inputs
let P_source = pubkey_source.get_point();
let C_source = ciphertext_source.commitment.get_point();
let D_source = ciphertext_source.handle.get_point();
let P_source = source_pubkey.get_point();
let C_source = source_ciphertext.commitment.get_point();
let D_source = source_ciphertext.handle.get_point();
let P_dest = pubkey_dest.get_point();
let C_dest = ciphertext_dest.commitment.get_point();
let D_dest = ciphertext_dest.handle.get_point();
let P_destination = destination_pubkey.get_point();
let C_destination = destination_ciphertext.commitment.get_point();
let D_destination = destination_ciphertext.handle.get_point();
// include Y_0, Y_1, Y_2 to transcript and extract challenges
transcript.validate_and_append_point(b"Y_0", &self.Y_0)?;
@ -385,20 +387,20 @@ impl CtxtCtxtEqualityProof {
&www_negated,
],
vec![
P_source, // P_source
&(*H), // H
&Y_0, // Y_0
&(*G), // G
D_source, // D_source
C_source, // C_source
&Y_1, // Y_1
&(*G), // G
&(*H), // H
C_dest, // C_dest
&Y_2, // Y_2
P_dest, // P_dest
D_dest, // D_dest
&Y_3, // Y_3
P_source, // P_source
&(*H), // H
&Y_0, // Y_0
&(*G), // G
D_source, // D_source
C_source, // C_source
&Y_1, // Y_1
&(*G), // G
&(*H), // H
C_destination, // C_destination
&Y_2, // Y_2
P_destination, // P_destination
D_destination, // D_destination
&Y_3, // Y_3
],
);
@ -456,57 +458,57 @@ mod test {
#[test]
fn test_ciphertext_commitment_equality_proof_correctness() {
// success case
let keypair_source = ElGamalKeypair::new_rand();
let source_keypair = ElGamalKeypair::new_rand();
let message: u64 = 55;
let ciphertext_source = keypair_source.public.encrypt(message);
let (commitment_dest, opening_dest) = Pedersen::new(message);
let source_ciphertext = source_keypair.public.encrypt(message);
let (destination_commitment, destination_opening) = Pedersen::new(message);
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new(
&keypair_source,
&ciphertext_source,
&source_keypair,
&source_ciphertext,
message,
&opening_dest,
&mut transcript_prover,
&destination_opening,
&mut prover_transcript,
);
assert!(proof
.verify(
&keypair_source.public,
&ciphertext_source,
&commitment_dest,
&mut transcript_verifier
&source_keypair.public,
&source_ciphertext,
&destination_commitment,
&mut verifier_transcript
)
.is_ok());
// 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 committed_message: u64 = 77;
let ciphertext_source = keypair_source.public.encrypt(encrypted_message);
let (commitment_dest, opening_dest) = Pedersen::new(committed_message);
let source_ciphertext = source_keypair.public.encrypt(encrypted_message);
let (destination_commitment, destination_opening) = Pedersen::new(committed_message);
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new(
&keypair_source,
&ciphertext_source,
&source_keypair,
&source_ciphertext,
message,
&opening_dest,
&mut transcript_prover,
&destination_opening,
&mut prover_transcript,
);
assert!(proof
.verify(
&keypair_source.public,
&ciphertext_source,
&commitment_dest,
&mut transcript_verifier
&source_keypair.public,
&source_ciphertext,
&destination_commitment,
&mut verifier_transcript
)
.is_err());
}
@ -523,15 +525,15 @@ mod test {
let ciphertext = elgamal_keypair.public.encrypt(message);
let (commitment, opening) = Pedersen::new(message);
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new(
&elgamal_keypair,
&ciphertext,
message,
&opening,
&mut transcript_prover,
&mut prover_transcript,
);
assert!(proof
@ -539,7 +541,7 @@ mod test {
&elgamal_keypair.public,
&ciphertext,
&commitment,
&mut transcript_verifier
&mut verifier_transcript
)
.is_err());
@ -552,15 +554,15 @@ mod test {
let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap();
let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap();
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new(
&elgamal_keypair,
&ciphertext,
message,
&opening,
&mut transcript_prover,
&mut prover_transcript,
);
assert!(proof
@ -568,7 +570,7 @@ mod test {
&elgamal_keypair.public,
&ciphertext,
&commitment,
&mut transcript_verifier
&mut verifier_transcript
)
.is_ok());
@ -581,15 +583,15 @@ mod test {
let commitment = PedersenCommitment::from_bytes(&[0u8; 32]).unwrap();
let opening = PedersenOpening::from_bytes(&[0u8; 32]).unwrap();
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new(
&elgamal_keypair,
&ciphertext,
message,
&opening,
&mut transcript_prover,
&mut prover_transcript,
);
assert!(proof
@ -597,7 +599,7 @@ mod test {
&elgamal_keypair.public,
&ciphertext,
&commitment,
&mut transcript_verifier
&mut verifier_transcript
)
.is_ok());
@ -609,15 +611,15 @@ mod test {
let ciphertext = ElGamalCiphertext::from_bytes(&[0u8; 64]).unwrap();
let (commitment, opening) = Pedersen::new(message);
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCommEqualityProof::new(
&elgamal_keypair,
&ciphertext,
message,
&opening,
&mut transcript_prover,
&mut prover_transcript,
);
assert!(proof
@ -625,7 +627,7 @@ mod test {
&elgamal_keypair.public,
&ciphertext,
&commitment,
&mut transcript_verifier
&mut verifier_transcript
)
.is_ok());
}
@ -633,67 +635,69 @@ mod test {
#[test]
fn test_ciphertext_ciphertext_equality_proof_correctness() {
// success case
let keypair_source = ElGamalKeypair::new_rand();
let keypair_dest = ElGamalKeypair::new_rand();
let source_keypair = ElGamalKeypair::new_rand();
let destination_keypair = ElGamalKeypair::new_rand();
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 ciphertext_dest = keypair_dest.public.encrypt_with(message, &opening_dest);
let destination_opening = PedersenOpening::new_rand();
let destination_ciphertext = destination_keypair
.public
.encrypt_with(message, &destination_opening);
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCtxtEqualityProof::new(
&keypair_source,
&keypair_dest.public,
&ciphertext_source,
&source_keypair,
&destination_keypair.public,
&source_ciphertext,
message,
&opening_dest,
&mut transcript_prover,
&destination_opening,
&mut prover_transcript,
);
assert!(proof
.verify(
&keypair_source.public,
&keypair_dest.public,
&ciphertext_source,
&ciphertext_dest,
&mut transcript_verifier
&source_keypair.public,
&destination_keypair.public,
&source_ciphertext,
&destination_ciphertext,
&mut verifier_transcript
)
.is_ok());
// fail case: encrypted and committed messages are different
let message_source: u64 = 55;
let message_dest: u64 = 77;
let source_message: u64 = 55;
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 ciphertext_dest = keypair_dest
let destination_opening = PedersenOpening::new_rand();
let destination_ciphertext = destination_keypair
.public
.encrypt_with(message_dest, &opening_dest);
.encrypt_with(destination_message, &destination_opening);
let mut transcript_prover = Transcript::new(b"Test");
let mut transcript_verifier = Transcript::new(b"Test");
let mut prover_transcript = Transcript::new(b"Test");
let mut verifier_transcript = Transcript::new(b"Test");
let proof = CtxtCtxtEqualityProof::new(
&keypair_source,
&keypair_dest.public,
&ciphertext_source,
&source_keypair,
&destination_keypair.public,
&source_ciphertext,
message,
&opening_dest,
&mut transcript_prover,
&destination_opening,
&mut prover_transcript,
);
assert!(proof
.verify(
&keypair_source.public,
&keypair_dest.public,
&ciphertext_source,
&ciphertext_dest,
&mut transcript_verifier
&source_keypair.public,
&destination_keypair.public,
&source_ciphertext,
&destination_ciphertext,
&mut verifier_transcript
)
.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
/// 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
/// * `(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
/// * `(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
/// * `max_fee` - The maximum fee bound
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn new(
(fee_amount, commitment_fee, opening_fee): (u64, &PedersenCommitment, &PedersenOpening),
(delta_fee, commitment_delta, opening_delta): (u64, &PedersenCommitment, &PedersenOpening),
(commitment_claimed, opening_claimed): (&PedersenCommitment, &PedersenOpening),
(fee_amount, fee_commitment, fee_opening): (u64, &PedersenCommitment, &PedersenOpening),
(delta_fee, delta_commitment, delta_opening): (u64, &PedersenCommitment, &PedersenOpening),
(claimed_commitment, claimed_opening): (&PedersenCommitment, &PedersenOpening),
max_fee: u64,
transcript: &mut Transcript,
) -> Self {
@ -60,16 +60,16 @@ impl FeeSigmaProof {
// 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(
opening_fee,
commitment_delta,
commitment_claimed,
fee_opening,
delta_commitment,
claimed_commitment,
&mut transcript_fee_above_max,
);
let proof_fee_below_max = Self::create_proof_fee_below_max(
commitment_fee,
(delta_fee, opening_delta),
opening_claimed,
fee_commitment,
(delta_fee, delta_opening),
claimed_opening,
max_fee,
&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
/// bound.
///
/// * `opening_fee` - The opening of the Pedersen commitment of the transfer fee
/// * `commitment_delta` - The Pedersen commitment of the "real" delta value
/// * `commitment_claimed` - The Pedersen commitment of the "claimed" delta value
/// * `fee_opening` - The opening of the Pedersen commitment of the transfer fee
/// * `delta_commitment` - The Pedersen commitment of the "real" delta value
/// * `claimed_commitment` - The Pedersen commitment of the "claimed" delta value
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
fn create_proof_fee_above_max(
opening_fee: &PedersenOpening,
commitment_delta: &PedersenCommitment,
commitment_claimed: &PedersenCommitment,
fee_opening: &PedersenOpening,
delta_commitment: &PedersenCommitment,
claimed_commitment: &PedersenCommitment,
transcript: &mut Transcript,
) -> Self {
// simulate equality proof
let C_delta = commitment_delta.get_point();
let C_claimed = commitment_claimed.get_point();
let C_delta = delta_commitment.get_point();
let C_claimed = claimed_commitment.get_point();
let z_x = Scalar::random(&mut OsRng);
let z_delta = Scalar::random(&mut OsRng);
@ -140,7 +140,7 @@ impl FeeSigmaProof {
};
// 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 = (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
/// bound.
///
/// * `commitment_fee` - The Pedersen commitment of the transfer fee
/// * `(delta_fee, opening_delta)` - The Pedersen commitment and opening of the "real" delta
/// * `fee_commitment` - The Pedersen commitment of the transfer fee
/// * `(delta_fee, delta_opening)` - The Pedersen commitment and opening of the "real" delta
/// 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
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
fn create_proof_fee_below_max(
commitment_fee: &PedersenCommitment,
(delta_fee, opening_delta): (u64, &PedersenOpening),
opening_claimed: &PedersenOpening,
fee_commitment: &PedersenCommitment,
(delta_fee, delta_opening): (u64, &PedersenOpening),
claimed_opening: &PedersenOpening,
max_fee: u64,
transcript: &mut Transcript,
) -> Self {
// simulate max proof
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 c_max_proof = Scalar::random(&mut OsRng); // random challenge
@ -207,8 +207,8 @@ impl FeeSigmaProof {
// generate equality proof
let x = Scalar::from(delta_fee);
let r_delta = opening_delta.get_scalar();
let r_claimed = opening_claimed.get_scalar();
let r_delta = delta_opening.get_scalar();
let r_claimed = claimed_opening.get_scalar();
let y_x = Scalar::random(&mut OsRng);
let y_delta = Scalar::random(&mut OsRng);
@ -248,25 +248,25 @@ impl FeeSigmaProof {
/// Fee sigma proof verifier.
///
/// * `commitment_fee` - The Pedersen commitment of the transfer fee
/// * `commitment_delta` - The Pedersen commitment of the "real" delta value
/// * `commitment_claimed` - The Pedersen commitment of the "claimed" delta value
/// * `fee_commitment` - The Pedersen commitment of the transfer fee
/// * `delta_commitment` - The Pedersen commitment of the "real" delta value
/// * `claimed_commitment` - The Pedersen commitment of the "claimed" delta value
/// * `max_fee` - The maximum fee bound
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
pub fn verify(
self,
commitment_fee: &PedersenCommitment,
commitment_delta: &PedersenCommitment,
commitment_claimed: &PedersenCommitment,
fee_commitment: &PedersenCommitment,
delta_commitment: &PedersenCommitment,
claimed_commitment: &PedersenCommitment,
max_fee: u64,
transcript: &mut Transcript,
) -> Result<(), FeeSigmaProofError> {
// extract the relevant scalar and Ristretto points from the input
let m = Scalar::from(max_fee);
let C_max = commitment_fee.get_point();
let C_delta = commitment_delta.get_point();
let C_claimed = commitment_claimed.get_point();
let C_max = fee_commitment.get_point();
let C_delta = delta_commitment.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_delta", &self.fee_equality_proof.Y_delta)?;
@ -455,39 +455,39 @@ mod test {
let transfer_amount: u64 = 55;
let max_fee: u64 = 3;
let rate_fee: u16 = 555; // 5.55%
let amount_fee: u64 = 4;
let fee_rate: u16 = 555; // 5.55%
let fee_amount: u64 = 4;
let delta: u64 = 9475; // 4*10000 - 55*555
let (commitment_transfer, opening_transfer) = Pedersen::new(transfer_amount);
let (commitment_fee, opening_fee) = Pedersen::new(max_fee);
let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
let (fee_commitment, fee_opening) = Pedersen::new(max_fee);
let scalar_rate = Scalar::from(rate_fee);
let commitment_delta =
&commitment_fee * &Scalar::from(10000_u64) - &commitment_transfer * &scalar_rate;
let opening_delta =
&opening_fee * &Scalar::from(10000_u64) - &opening_transfer * &scalar_rate;
let scalar_rate = Scalar::from(fee_rate);
let delta_commitment =
&fee_commitment * &Scalar::from(10000_u64) - &transfer_commitment * &scalar_rate;
let delta_opening =
&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 transcript_verifier = Transcript::new(b"test");
let mut prover_transcript = Transcript::new(b"test");
let mut verifier_transcript = Transcript::new(b"test");
let proof = FeeSigmaProof::new(
(amount_fee, &commitment_fee, &opening_fee),
(delta, &commitment_delta, &opening_delta),
(&commitment_claimed, &opening_claimed),
(fee_amount, &fee_commitment, &fee_opening),
(delta, &delta_commitment, &delta_opening),
(&claimed_commitment, &claimed_opening),
max_fee,
&mut transcript_prover,
&mut prover_transcript,
);
assert!(proof
.verify(
&commitment_fee,
&commitment_delta,
&commitment_claimed,
&fee_commitment,
&delta_commitment,
&claimed_commitment,
max_fee,
&mut transcript_verifier,
&mut verifier_transcript,
)
.is_ok());
}
@ -497,44 +497,44 @@ mod test {
let transfer_amount: u64 = 55;
let max_fee: u64 = 77;
let rate_fee: u16 = 555; // 5.55%
let amount_fee: u64 = 4;
let fee_rate: u16 = 555; // 5.55%
let fee_amount: u64 = 4;
let delta: u64 = 9475; // 4*10000 - 55*555
let (commitment_transfer, opening_transfer) = Pedersen::new(transfer_amount);
let (commitment_fee, opening_fee) = Pedersen::new(amount_fee);
let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
let (fee_commitment, fee_opening) = Pedersen::new(fee_amount);
let scalar_rate = Scalar::from(rate_fee);
let commitment_delta =
&commitment_fee * &Scalar::from(10000_u64) - &commitment_transfer * &scalar_rate;
let opening_delta =
&opening_fee * &Scalar::from(10000_u64) - &opening_transfer * &scalar_rate;
let scalar_rate = Scalar::from(fee_rate);
let delta_commitment =
&fee_commitment * &Scalar::from(10000_u64) - &transfer_commitment * &scalar_rate;
let delta_opening =
&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!(
commitment_delta.get_point() - opening_delta.get_scalar() * &(*H),
commitment_claimed.get_point() - opening_claimed.get_scalar() * &(*H)
delta_commitment.get_point() - delta_opening.get_scalar() * &(*H),
claimed_commitment.get_point() - claimed_opening.get_scalar() * &(*H)
);
let mut transcript_prover = Transcript::new(b"test");
let mut transcript_verifier = Transcript::new(b"test");
let mut prover_transcript = Transcript::new(b"test");
let mut verifier_transcript = Transcript::new(b"test");
let proof = FeeSigmaProof::new(
(amount_fee, &commitment_fee, &opening_fee),
(delta, &commitment_delta, &opening_delta),
(&commitment_claimed, &opening_claimed),
(fee_amount, &fee_commitment, &fee_opening),
(delta, &delta_commitment, &delta_opening),
(&claimed_commitment, &claimed_opening),
max_fee,
&mut transcript_prover,
&mut prover_transcript,
);
assert!(proof
.verify(
&commitment_fee,
&commitment_delta,
&commitment_claimed,
&fee_commitment,
&delta_commitment,
&claimed_commitment,
max_fee,
&mut transcript_verifier,
&mut verifier_transcript,
)
.is_ok());
}
@ -544,39 +544,39 @@ mod test {
let transfer_amount: u64 = 100;
let max_fee: u64 = 3;
let rate_fee: u16 = 100; // 1.00%
let amount_fee: u64 = 1;
let fee_rate: u16 = 100; // 1.00%
let fee_amount: u64 = 1;
let delta: u64 = 0; // 1*10000 - 100*100
let (commitment_transfer, opening_transfer) = Pedersen::new(transfer_amount);
let (commitment_fee, opening_fee) = Pedersen::new(amount_fee);
let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
let (fee_commitment, fee_opening) = Pedersen::new(fee_amount);
let scalar_rate = Scalar::from(rate_fee);
let commitment_delta =
&(&commitment_fee * &Scalar::from(10000_u64)) - &(&commitment_transfer * &scalar_rate);
let opening_delta =
&(&opening_fee * &Scalar::from(10000_u64)) - &(&opening_transfer * &scalar_rate);
let scalar_rate = Scalar::from(fee_rate);
let delta_commitment =
&(&fee_commitment * &Scalar::from(10000_u64)) - &(&transfer_commitment * &scalar_rate);
let delta_opening =
&(&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 transcript_verifier = Transcript::new(b"test");
let mut prover_transcript = Transcript::new(b"test");
let mut verifier_transcript = Transcript::new(b"test");
let proof = FeeSigmaProof::new(
(amount_fee, &commitment_fee, &opening_fee),
(delta, &commitment_delta, &opening_delta),
(&commitment_claimed, &opening_claimed),
(fee_amount, &fee_commitment, &fee_opening),
(delta, &delta_commitment, &delta_opening),
(&claimed_commitment, &claimed_opening),
max_fee,
&mut transcript_prover,
&mut prover_transcript,
);
assert!(proof
.verify(
&commitment_fee,
&commitment_delta,
&commitment_claimed,
&fee_commitment,
&delta_commitment,
&claimed_commitment,
max_fee,
&mut transcript_verifier,
&mut verifier_transcript,
)
.is_ok());
}

View File

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

View File

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

View File

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

View File

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