diff --git a/zk-token-sdk/src/instruction/batched_grouped_ciphertext_validity.rs b/zk-token-sdk/src/instruction/batched_grouped_ciphertext_validity.rs index 899707adce7bb2..db61c0f2f40b02 100644 --- a/zk-token-sdk/src/instruction/batched_grouped_ciphertext_validity.rs +++ b/zk-token-sdk/src/instruction/batched_grouped_ciphertext_validity.rs @@ -20,7 +20,7 @@ use { pedersen::PedersenOpening, }, errors::ProofError, - sigma_proofs::validity_proof::AggregatedValidityProof, + sigma_proofs::batched_grouped_ciphertext_validity_proof::BatchedGroupedCiphertext2HandlesValidityProof, transcript::TranscriptProtocol, }, merlin::Transcript, @@ -43,7 +43,7 @@ use { pub struct BatchedGroupedCiphertext2HandlesValidityProofData { pub context: BatchedGroupedCiphertext2HandlesValidityProofContext, - pub proof: pod::AggregatedValidityProof, + pub proof: pod::BatchedGroupedCiphertext2HandlesValidityProof, } #[derive(Clone, Copy, Pod, Zeroable)] @@ -84,7 +84,7 @@ impl BatchedGroupedCiphertext2HandlesValidityProofData { let mut transcript = context.new_transcript(); - let proof = AggregatedValidityProof::new( + let proof = BatchedGroupedCiphertext2HandlesValidityProof::new( (destination_pubkey, auditor_pubkey), (amount_lo, amount_hi), (opening_lo, opening_hi), @@ -122,7 +122,7 @@ impl ZkProofData let destination_handle_hi = grouped_ciphertext_hi.handles.get(0).unwrap(); let auditor_handle_hi = grouped_ciphertext_hi.handles.get(1).unwrap(); - let proof: AggregatedValidityProof = self.proof.try_into()?; + let proof: BatchedGroupedCiphertext2HandlesValidityProof = self.proof.try_into()?; proof .verify( diff --git a/zk-token-sdk/src/instruction/grouped_ciphertext_validity.rs b/zk-token-sdk/src/instruction/grouped_ciphertext_validity.rs index 4b74e2cc5904fb..1c71c61aa84322 100644 --- a/zk-token-sdk/src/instruction/grouped_ciphertext_validity.rs +++ b/zk-token-sdk/src/instruction/grouped_ciphertext_validity.rs @@ -18,7 +18,7 @@ use { pedersen::PedersenOpening, }, errors::ProofError, - sigma_proofs::validity_proof::ValidityProof, + sigma_proofs::grouped_ciphertext_validity_proof::GroupedCiphertext2HandlesValidityProof, transcript::TranscriptProtocol, }, merlin::Transcript, @@ -41,7 +41,7 @@ use { pub struct GroupedCiphertext2HandlesValidityProofData { pub context: GroupedCiphertext2HandlesValidityProofContext, - pub proof: pod::ValidityProof, + pub proof: pod::GroupedCiphertext2HandlesValidityProof, } #[derive(Clone, Copy, Pod, Zeroable)] @@ -75,7 +75,7 @@ impl GroupedCiphertext2HandlesValidityProofData { let mut transcript = context.new_transcript(); - let proof = ValidityProof::new( + let proof = GroupedCiphertext2HandlesValidityProof::new( (destination_pubkey, auditor_pubkey), amount, opening, @@ -108,7 +108,7 @@ impl ZkProofData let destination_handle = grouped_ciphertext.handles.get(0).unwrap(); let auditor_handle = grouped_ciphertext.handles.get(1).unwrap(); - let proof: ValidityProof = self.proof.try_into()?; + let proof: GroupedCiphertext2HandlesValidityProof = self.proof.try_into()?; proof .verify( diff --git a/zk-token-sdk/src/instruction/transfer/with_fee.rs b/zk-token-sdk/src/instruction/transfer/with_fee.rs index e1ffbc3e722ecf..c831ca0eb1a971 100644 --- a/zk-token-sdk/src/instruction/transfer/with_fee.rs +++ b/zk-token-sdk/src/instruction/transfer/with_fee.rs @@ -14,8 +14,9 @@ use { }, range_proof::RangeProof, sigma_proofs::{ + batched_grouped_ciphertext_validity_proof::BatchedGroupedCiphertext2HandlesValidityProof, ciphertext_commitment_equality_proof::CiphertextCommitmentEqualityProof, - fee_proof::FeeSigmaProof, validity_proof::AggregatedValidityProof, + fee_proof::FeeSigmaProof, }, transcript::TranscriptProtocol, }, @@ -399,9 +400,9 @@ pub struct TransferWithFeeProof { pub new_source_commitment: pod::PedersenCommitment, pub claimed_commitment: pod::PedersenCommitment, pub equality_proof: pod::CiphertextCommitmentEqualityProof, - pub ciphertext_amount_validity_proof: pod::AggregatedValidityProof, + pub ciphertext_amount_validity_proof: pod::BatchedGroupedCiphertext2HandlesValidityProof, pub fee_sigma_proof: pod::FeeSigmaProof, - pub fee_ciphertext_validity_proof: pod::AggregatedValidityProof, + pub fee_ciphertext_validity_proof: pod::BatchedGroupedCiphertext2HandlesValidityProof, pub range_proof: pod::RangeProofU256, } @@ -443,7 +444,7 @@ impl TransferWithFeeProof { ); // generate ciphertext validity proof - let ciphertext_amount_validity_proof = AggregatedValidityProof::new( + let ciphertext_amount_validity_proof = BatchedGroupedCiphertext2HandlesValidityProof::new( (destination_pubkey, auditor_pubkey), (transfer_amount_lo, transfer_amount_hi), (opening_lo, opening_hi), @@ -496,7 +497,7 @@ impl TransferWithFeeProof { ); // generate ciphertext validity proof for fee ciphertexts - let fee_ciphertext_validity_proof = AggregatedValidityProof::new( + let fee_ciphertext_validity_proof = BatchedGroupedCiphertext2HandlesValidityProof::new( (destination_pubkey, withdraw_withheld_authority_pubkey), (fee_amount_lo, fee_amount_hi), (opening_fee_lo, opening_fee_hi), @@ -565,10 +566,10 @@ impl TransferWithFeeProof { let claimed_commitment: PedersenCommitment = self.claimed_commitment.try_into()?; let equality_proof: CiphertextCommitmentEqualityProof = self.equality_proof.try_into()?; - let ciphertext_amount_validity_proof: AggregatedValidityProof = + let ciphertext_amount_validity_proof: BatchedGroupedCiphertext2HandlesValidityProof = self.ciphertext_amount_validity_proof.try_into()?; let fee_sigma_proof: FeeSigmaProof = self.fee_sigma_proof.try_into()?; - let fee_ciphertext_validity_proof: AggregatedValidityProof = + let fee_ciphertext_validity_proof: BatchedGroupedCiphertext2HandlesValidityProof = self.fee_ciphertext_validity_proof.try_into()?; let range_proof: RangeProof = self.range_proof.try_into()?; diff --git a/zk-token-sdk/src/instruction/transfer/without_fee.rs b/zk-token-sdk/src/instruction/transfer/without_fee.rs index 74df4fa9f8236f..0ef815f0ac268b 100644 --- a/zk-token-sdk/src/instruction/transfer/without_fee.rs +++ b/zk-token-sdk/src/instruction/transfer/without_fee.rs @@ -11,8 +11,8 @@ use { }, range_proof::RangeProof, sigma_proofs::{ + batched_grouped_ciphertext_validity_proof::BatchedGroupedCiphertext2HandlesValidityProof, ciphertext_commitment_equality_proof::CiphertextCommitmentEqualityProof, - validity_proof::AggregatedValidityProof, }, transcript::TranscriptProtocol, }, @@ -267,7 +267,7 @@ pub struct TransferProof { pub equality_proof: pod::CiphertextCommitmentEqualityProof, /// Associated ciphertext validity proof - pub validity_proof: pod::AggregatedValidityProof, + pub validity_proof: pod::BatchedGroupedCiphertext2HandlesValidityProof, // Associated range proof pub range_proof: pod::RangeProofU128, @@ -301,7 +301,7 @@ impl TransferProof { ); // generate ciphertext validity proof - let validity_proof = AggregatedValidityProof::new( + let validity_proof = BatchedGroupedCiphertext2HandlesValidityProof::new( (destination_pubkey, auditor_pubkey), (transfer_amount_lo, transfer_amount_hi), (opening_lo, opening_hi), @@ -363,7 +363,8 @@ impl TransferProof { let commitment: PedersenCommitment = self.new_source_commitment.try_into()?; let equality_proof: CiphertextCommitmentEqualityProof = self.equality_proof.try_into()?; - let aggregated_validity_proof: AggregatedValidityProof = self.validity_proof.try_into()?; + let aggregated_validity_proof: BatchedGroupedCiphertext2HandlesValidityProof = + self.validity_proof.try_into()?; let range_proof: RangeProof = self.range_proof.try_into()?; // verify equality proof diff --git a/zk-token-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity_proof.rs b/zk-token-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity_proof.rs new file mode 100644 index 00000000000000..c3de95619239ae --- /dev/null +++ b/zk-token-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity_proof.rs @@ -0,0 +1,155 @@ +//! The ciphertext validity sigma proof system. +//! +//! The ciphertext validity proof is defined with respect to a Pedersen commitment and two +//! decryption handles. The proof certifies that a given Pedersen commitment can be decrypted using +//! ElGamal private keys that are associated with each of the two decryption handles. To generate +//! the proof, a prover must provide the Pedersen opening associated with the commitment. +//! +//! The protocol guarantees computational soundness (by the hardness of discrete log) and perfect +//! zero-knowledge in the random oracle model. + +#[cfg(not(target_os = "solana"))] +use crate::encryption::{ + elgamal::{DecryptHandle, ElGamalPubkey}, + pedersen::{PedersenCommitment, PedersenOpening}, +}; +use { + crate::{ + sigma_proofs::{ + errors::ValidityProofError, + grouped_ciphertext_validity_proof::GroupedCiphertext2HandlesValidityProof, + }, + transcript::TranscriptProtocol, + }, + curve25519_dalek::scalar::Scalar, + merlin::Transcript, +}; + +/// Batched grouped ciphertext validity proof with two handles. +/// +/// A batched grouped ciphertext validity proof certifies the validity of two instances of a +/// standard ciphertext validity proof. An instance of a standard validity proof consists of one +/// ciphertext and two decryption handles: `(commitment, destination_handle, auditor_handle)`. An +/// instance of a batched 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 pairs of commitment and decryption handles. +#[allow(non_snake_case)] +#[derive(Clone)] +pub struct BatchedGroupedCiphertext2HandlesValidityProof(GroupedCiphertext2HandlesValidityProof); + +#[allow(non_snake_case)] +#[cfg(not(target_os = "solana"))] +impl BatchedGroupedCiphertext2HandlesValidityProof { + /// Batched grouped ciphertext validity proof constructor. + /// + /// The function simply batches the input openings and invokes the standard grouped ciphertext + /// validity proof constructor. + pub fn new>( + (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), + (amount_lo, amount_hi): (T, T), + (opening_lo, opening_hi): (&PedersenOpening, &PedersenOpening), + transcript: &mut Transcript, + ) -> Self { + transcript.batched_grouped_ciphertext_validity_proof_domain_sep(); + + let t = transcript.challenge_scalar(b"t"); + + let batched_message = amount_lo.into() + amount_hi.into() * t; + let batched_opening = opening_lo + &(opening_hi * &t); + + BatchedGroupedCiphertext2HandlesValidityProof(GroupedCiphertext2HandlesValidityProof::new( + (destination_pubkey, auditor_pubkey), + batched_message, + &batched_opening, + transcript, + )) + } + + /// Batched grouped ciphertext validity proof verifier. + /// + /// The function does *not* hash the public keys, commitment, or decryption handles into the + /// transcript. For security, the caller (the main protocol) should hash these public + /// components prior to invoking this constructor. + /// + /// This function is randomized. It uses `OsRng` internally to generate random scalars. + pub fn verify( + self, + (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), + (commitment_lo, commitment_hi): (&PedersenCommitment, &PedersenCommitment), + (destination_handle_lo, destination_handle_hi): (&DecryptHandle, &DecryptHandle), + (auditor_handle_lo, auditor_handle_hi): (&DecryptHandle, &DecryptHandle), + transcript: &mut Transcript, + ) -> Result<(), ValidityProofError> { + transcript.batched_grouped_ciphertext_validity_proof_domain_sep(); + + let t = transcript.challenge_scalar(b"t"); + + let batched_commitment = commitment_lo + commitment_hi * t; + let destination_batched_handle = destination_handle_lo + destination_handle_hi * t; + let auditor_batched_handle = auditor_handle_lo + auditor_handle_hi * t; + + let BatchedGroupedCiphertext2HandlesValidityProof(validity_proof) = self; + + validity_proof.verify( + &batched_commitment, + (destination_pubkey, auditor_pubkey), + (&destination_batched_handle, &auditor_batched_handle), + transcript, + ) + } + + pub fn to_bytes(&self) -> [u8; 160] { + self.0.to_bytes() + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + GroupedCiphertext2HandlesValidityProof::from_bytes(bytes).map(Self) + } +} + +#[cfg(test)] +mod test { + use { + super::*, + crate::encryption::{elgamal::ElGamalKeypair, pedersen::Pedersen}, + }; + + #[test] + fn test_batched_grouped_ciphertext_validity_proof() { + let destination_pubkey = ElGamalKeypair::new_rand().public; + let auditor_pubkey = ElGamalKeypair::new_rand().public; + + let amount_lo: u64 = 55; + let amount_hi: u64 = 77; + + let (commitment_lo, open_lo) = Pedersen::new(amount_lo); + let (commitment_hi, open_hi) = Pedersen::new(amount_hi); + + let destination_handle_lo = destination_pubkey.decrypt_handle(&open_lo); + let destination_handle_hi = destination_pubkey.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 prover_transcript = Transcript::new(b"Test"); + let mut verifier_transcript = Transcript::new(b"Test"); + + let proof = BatchedGroupedCiphertext2HandlesValidityProof::new( + (&destination_pubkey, &auditor_pubkey), + (amount_lo, amount_hi), + (&open_lo, &open_hi), + &mut prover_transcript, + ); + + assert!(proof + .verify( + (&destination_pubkey, &auditor_pubkey), + (&commitment_lo, &commitment_hi), + (&destination_handle_lo, &destination_handle_hi), + (&auditor_handle_lo, &auditor_handle_hi), + &mut verifier_transcript, + ) + .is_ok()); + } +} diff --git a/zk-token-sdk/src/sigma_proofs/validity_proof.rs b/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof.rs similarity index 70% rename from zk-token-sdk/src/sigma_proofs/validity_proof.rs rename to zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof.rs index ee55d0c0236e9e..6b73df746f4a0f 100644 --- a/zk-token-sdk/src/sigma_proofs/validity_proof.rs +++ b/zk-token-sdk/src/sigma_proofs/grouped_ciphertext_validity_proof.rs @@ -32,12 +32,12 @@ use { merlin::Transcript, }; -/// The ciphertext validity proof. +/// The grouped ciphertext validity proof for 2 handles. /// /// Contains all the elliptic curve and scalar components that make up the sigma protocol. #[allow(non_snake_case)] #[derive(Clone)] -pub struct ValidityProof { +pub struct GroupedCiphertext2HandlesValidityProof { Y_0: CompressedRistretto, Y_1: CompressedRistretto, Y_2: CompressedRistretto, @@ -47,8 +47,8 @@ pub struct ValidityProof { #[allow(non_snake_case)] #[cfg(not(target_os = "solana"))] -impl ValidityProof { - /// The ciphertext validity proof constructor. +impl GroupedCiphertext2HandlesValidityProof { + /// Creates a grouped ciphertext validity proof for 2 handles. /// /// The function does *not* hash the public keys, commitment, or decryption handles into the /// transcript. For security, the caller (the main protocol) should hash these public @@ -70,7 +70,7 @@ impl ValidityProof { opening: &PedersenOpening, transcript: &mut Transcript, ) -> Self { - transcript.validity_proof_domain_sep(); + transcript.grouped_ciphertext_validity_proof_domain_sep(); // extract the relevant scalar and Ristretto points from the inputs let P_dest = destination_pubkey.get_point(); @@ -111,7 +111,7 @@ impl ValidityProof { } } - /// The ciphertext validity proof verifier. + /// Verifies a grouped ciphertext validity proof for 2 handles. /// /// * `commitment` - The Pedersen commitment /// * `(destination_pubkey, auditor_pubkey)` - The ElGamal pubkeys associated with the decryption @@ -125,7 +125,7 @@ impl ValidityProof { (destination_handle, auditor_handle): (&DecryptHandle, &DecryptHandle), transcript: &mut Transcript, ) -> Result<(), ValidityProofError> { - transcript.validity_proof_domain_sep(); + transcript.grouped_ciphertext_validity_proof_domain_sep(); // include Y_0, Y_1, Y_2 to transcript and extract challenges transcript.validate_and_append_point(b"Y_0", &self.Y_0)?; @@ -221,7 +221,7 @@ impl ValidityProof { let z_x = Scalar::from_canonical_bytes(*z_x).ok_or(ProofVerificationError::Deserialization)?; - Ok(ValidityProof { + Ok(GroupedCiphertext2HandlesValidityProof { Y_0, Y_1, Y_2, @@ -231,89 +231,6 @@ impl ValidityProof { } } -/// Aggregated ciphertext validity proof. -/// -/// 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, 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)] -#[derive(Clone)] -pub struct AggregatedValidityProof(ValidityProof); - -#[allow(non_snake_case)] -#[cfg(not(target_os = "solana"))] -impl AggregatedValidityProof { - /// Aggregated ciphertext validity proof constructor. - /// - /// The function simples aggregates the input openings and invokes the standard ciphertext - /// validity proof constructor. - pub fn new>( - (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), - (amount_lo, amount_hi): (T, T), - (opening_lo, opening_hi): (&PedersenOpening, &PedersenOpening), - transcript: &mut Transcript, - ) -> Self { - transcript.aggregated_validity_proof_domain_sep(); - - let t = transcript.challenge_scalar(b"t"); - - let aggregated_message = amount_lo.into() + amount_hi.into() * t; - let aggregated_opening = opening_lo + &(opening_hi * &t); - - AggregatedValidityProof(ValidityProof::new( - (destination_pubkey, auditor_pubkey), - aggregated_message, - &aggregated_opening, - transcript, - )) - } - - /// Aggregated ciphertext validity proof verifier. - /// - /// The function does *not* hash the public keys, commitment, or decryption handles into the - /// transcript. For security, the caller (the main protocol) should hash these public - /// components prior to invoking this constructor. - /// - /// This function is randomized. It uses `OsRng` internally to generate random scalars. - pub fn verify( - self, - (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), - (commitment_lo, commitment_hi): (&PedersenCommitment, &PedersenCommitment), - (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(); - - let t = transcript.challenge_scalar(b"t"); - - let aggregated_commitment = commitment_lo + commitment_hi * 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, - (destination_pubkey, auditor_pubkey), - (&destination_aggregated_handle, &auditor_aggregated_handle), - transcript, - ) - } - - pub fn to_bytes(&self) -> [u8; 160] { - self.0.to_bytes() - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - ValidityProof::from_bytes(bytes).map(Self) - } -} - #[cfg(test)] mod test { use { @@ -322,7 +239,7 @@ mod test { }; #[test] - fn test_validity_proof_correctness() { + fn test_grouped_ciphertext_validity_proof_correctness() { let destination_pubkey = ElGamalKeypair::new_rand().public; let auditor_pubkey = ElGamalKeypair::new_rand().public; @@ -335,7 +252,7 @@ mod test { let mut prover_transcript = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test"); - let proof = ValidityProof::new( + let proof = GroupedCiphertext2HandlesValidityProof::new( (&destination_pubkey, &auditor_pubkey), amount, &opening, @@ -353,7 +270,7 @@ mod test { } #[test] - fn test_validity_proof_edge_cases() { + fn test_grouped_ciphertext_validity_proof_edge_cases() { // if destination public key zeroed, then the proof should always reject let destination_pubkey = ElGamalPubkey::from_bytes(&[0u8; 32]).unwrap(); let auditor_pubkey = ElGamalKeypair::new_rand().public; @@ -367,7 +284,7 @@ mod test { let mut prover_transcript = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test"); - let proof = ValidityProof::new( + let proof = GroupedCiphertext2HandlesValidityProof::new( (&destination_pubkey, &auditor_pubkey), amount, &opening, @@ -396,7 +313,7 @@ mod test { let mut prover_transcript = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test"); - let proof = ValidityProof::new( + let proof = GroupedCiphertext2HandlesValidityProof::new( (&destination_pubkey, &auditor_pubkey), amount, &opening, @@ -426,7 +343,7 @@ mod test { let mut prover_transcript = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test"); - let proof = ValidityProof::new( + let proof = GroupedCiphertext2HandlesValidityProof::new( (&destination_pubkey, &auditor_pubkey), amount, &opening, @@ -455,7 +372,7 @@ mod test { let mut prover_transcript = Transcript::new(b"Test"); let mut verifier_transcript = Transcript::new(b"Test"); - let proof = ValidityProof::new( + let proof = GroupedCiphertext2HandlesValidityProof::new( (&destination_pubkey, &auditor_pubkey), amount, &opening, @@ -471,42 +388,4 @@ mod test { ) .is_ok()); } - - #[test] - fn test_aggregated_validity_proof() { - let destination_pubkey = ElGamalKeypair::new_rand().public; - let auditor_pubkey = ElGamalKeypair::new_rand().public; - - let amount_lo: u64 = 55; - let amount_hi: u64 = 77; - - let (commitment_lo, open_lo) = Pedersen::new(amount_lo); - let (commitment_hi, open_hi) = Pedersen::new(amount_hi); - - let destination_handle_lo = destination_pubkey.decrypt_handle(&open_lo); - let destination_handle_hi = destination_pubkey.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 prover_transcript = Transcript::new(b"Test"); - let mut verifier_transcript = Transcript::new(b"Test"); - - let proof = AggregatedValidityProof::new( - (&destination_pubkey, &auditor_pubkey), - (amount_lo, amount_hi), - (&open_lo, &open_hi), - &mut prover_transcript, - ); - - assert!(proof - .verify( - (&destination_pubkey, &auditor_pubkey), - (&commitment_lo, &commitment_hi), - (&destination_handle_lo, &destination_handle_hi), - (&auditor_handle_lo, &auditor_handle_hi), - &mut verifier_transcript, - ) - .is_ok()); - } } diff --git a/zk-token-sdk/src/sigma_proofs/mod.rs b/zk-token-sdk/src/sigma_proofs/mod.rs index 587961ca72e3b4..7ce550f4a0d047 100644 --- a/zk-token-sdk/src/sigma_proofs/mod.rs +++ b/zk-token-sdk/src/sigma_proofs/mod.rs @@ -15,10 +15,11 @@ //! We refer to the zk-token paper for the formal details and security proofs of these argument //! systems. +pub mod batched_grouped_ciphertext_validity_proof; pub mod ciphertext_ciphertext_equality_proof; pub mod ciphertext_commitment_equality_proof; pub mod errors; pub mod fee_proof; +pub mod grouped_ciphertext_validity_proof; pub mod pubkey_proof; -pub mod validity_proof; pub mod zero_balance_proof; diff --git a/zk-token-sdk/src/transcript.rs b/zk-token-sdk/src/transcript.rs index 8a35753c336cbf..31f6edde1ef535 100644 --- a/zk-token-sdk/src/transcript.rs +++ b/zk-token-sdk/src/transcript.rs @@ -56,11 +56,11 @@ pub trait TranscriptProtocol { /// Append a domain separator for zero-balance proof. fn zero_balance_proof_domain_sep(&mut self); - /// Append a domain separator for validity proof. - fn validity_proof_domain_sep(&mut self); + /// Append a domain separator for grouped ciphertext validity proof. + fn grouped_ciphertext_validity_proof_domain_sep(&mut self); - /// Append a domain separator for aggregated validity proof. - fn aggregated_validity_proof_domain_sep(&mut self); + /// Append a domain separator for batched grouped ciphertext validity proof. + fn batched_grouped_ciphertext_validity_proof_domain_sep(&mut self); /// Append a domain separator for fee sigma proof. fn fee_sigma_proof_domain_sep(&mut self); @@ -168,12 +168,12 @@ impl TranscriptProtocol for Transcript { self.append_message(b"dom-sep", b"zero-balance-proof") } - fn validity_proof_domain_sep(&mut self) { + fn grouped_ciphertext_validity_proof_domain_sep(&mut self) { self.append_message(b"dom-sep", b"validity-proof") } - fn aggregated_validity_proof_domain_sep(&mut self) { - self.append_message(b"dom-sep", b"aggregated-validity-proof") + fn batched_grouped_ciphertext_validity_proof_domain_sep(&mut self) { + self.append_message(b"dom-sep", b"batched-validity-proof") } fn fee_sigma_proof_domain_sep(&mut self) { diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/mod.rs b/zk-token-sdk/src/zk_token_elgamal/pod/mod.rs index d75e4b6caf0e28..cf2d3c3b9772a8 100644 --- a/zk-token-sdk/src/zk_token_elgamal/pod/mod.rs +++ b/zk-token-sdk/src/zk_token_elgamal/pod/mod.rs @@ -23,9 +23,9 @@ pub use { pedersen::PedersenCommitment, range_proof::{RangeProofU128, RangeProofU256, RangeProofU64}, sigma_proofs::{ - AggregatedValidityProof, CiphertextCiphertextEqualityProof, - CiphertextCommitmentEqualityProof, FeeSigmaProof, PubkeyValidityProof, ValidityProof, - ZeroBalanceProof, + BatchedGroupedCiphertext2HandlesValidityProof, CiphertextCiphertextEqualityProof, + CiphertextCommitmentEqualityProof, FeeSigmaProof, GroupedCiphertext2HandlesValidityProof, + PubkeyValidityProof, ZeroBalanceProof, }, }; diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs b/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs index 4cb96902dedff3..f77d43b5baaca9 100644 --- a/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs +++ b/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs @@ -2,15 +2,12 @@ #[cfg(not(target_os = "solana"))] use crate::sigma_proofs::{ + batched_grouped_ciphertext_validity_proof::BatchedGroupedCiphertext2HandlesValidityProof as DecodedBatchedGroupedCiphertext2HandlesValidityProof, ciphertext_ciphertext_equality_proof::CiphertextCiphertextEqualityProof as DecodedCiphertextCiphertextEqualityProof, ciphertext_commitment_equality_proof::CiphertextCommitmentEqualityProof as DecodedCiphertextCommitmentEqualityProof, - errors::*, - fee_proof::FeeSigmaProof as DecodedFeeSigmaProof, + errors::*, fee_proof::FeeSigmaProof as DecodedFeeSigmaProof, + grouped_ciphertext_validity_proof::GroupedCiphertext2HandlesValidityProof as DecodedGroupedCiphertext2HandlesValidityProof, pubkey_proof::PubkeyValidityProof as DecodedPubkeyValidityProof, - validity_proof::{ - AggregatedValidityProof as DecodedAggregatedValidityProof, - ValidityProof as DecodedValidityProof, - }, zero_balance_proof::ZeroBalanceProof as DecodedZeroBalanceProof, }; use crate::zk_token_elgamal::pod::{Pod, Zeroable}; @@ -57,44 +54,54 @@ impl TryFrom for DecodedCiphertextCiphertextE } } -/// The `ValidityProof` type as a `Pod`. +/// The `GroupedCiphertext2HandlesValidityProof` type as a `Pod`. #[derive(Clone, Copy)] #[repr(transparent)] -pub struct ValidityProof(pub [u8; 160]); +pub struct GroupedCiphertext2HandlesValidityProof(pub [u8; 160]); #[cfg(not(target_os = "solana"))] -impl From for ValidityProof { - fn from(decoded_proof: DecodedValidityProof) -> Self { +impl From + for GroupedCiphertext2HandlesValidityProof +{ + fn from(decoded_proof: DecodedGroupedCiphertext2HandlesValidityProof) -> Self { Self(decoded_proof.to_bytes()) } } #[cfg(not(target_os = "solana"))] -impl TryFrom for DecodedValidityProof { +impl TryFrom + for DecodedGroupedCiphertext2HandlesValidityProof +{ type Error = ValidityProofError; - fn try_from(pod_proof: ValidityProof) -> Result { + fn try_from(pod_proof: GroupedCiphertext2HandlesValidityProof) -> Result { Self::from_bytes(&pod_proof.0) } } -/// The `AggregatedValidityProof` type as a `Pod`. +/// The `BatchedGroupedCiphertext2HandlesValidityProof` type as a `Pod`. #[derive(Clone, Copy)] #[repr(transparent)] -pub struct AggregatedValidityProof(pub [u8; 160]); +pub struct BatchedGroupedCiphertext2HandlesValidityProof(pub [u8; 160]); #[cfg(not(target_os = "solana"))] -impl From for AggregatedValidityProof { - fn from(decoded_proof: DecodedAggregatedValidityProof) -> Self { +impl From + for BatchedGroupedCiphertext2HandlesValidityProof +{ + fn from(decoded_proof: DecodedBatchedGroupedCiphertext2HandlesValidityProof) -> Self { Self(decoded_proof.to_bytes()) } } #[cfg(not(target_os = "solana"))] -impl TryFrom for DecodedAggregatedValidityProof { +impl TryFrom + for DecodedBatchedGroupedCiphertext2HandlesValidityProof +{ type Error = ValidityProofError; - fn try_from(pod_proof: AggregatedValidityProof) -> Result { + fn try_from( + pod_proof: BatchedGroupedCiphertext2HandlesValidityProof, + ) -> Result { Self::from_bytes(&pod_proof.0) } } @@ -171,11 +178,11 @@ unsafe impl Pod for CiphertextCommitmentEqualityProof {} unsafe impl Zeroable for CiphertextCiphertextEqualityProof {} unsafe impl Pod for CiphertextCiphertextEqualityProof {} -unsafe impl Zeroable for ValidityProof {} -unsafe impl Pod for ValidityProof {} +unsafe impl Zeroable for GroupedCiphertext2HandlesValidityProof {} +unsafe impl Pod for GroupedCiphertext2HandlesValidityProof {} -unsafe impl Zeroable for AggregatedValidityProof {} -unsafe impl Pod for AggregatedValidityProof {} +unsafe impl Zeroable for BatchedGroupedCiphertext2HandlesValidityProof {} +unsafe impl Pod for BatchedGroupedCiphertext2HandlesValidityProof {} unsafe impl Zeroable for ZeroBalanceProof {} unsafe impl Pod for ZeroBalanceProof {}