solana_zk_token_sdk/instruction/grouped_ciphertext_validity/
handles_2.rs1#[cfg(not(target_os = "solana"))]
14use {
15 crate::{
16 encryption::{
17 elgamal::ElGamalPubkey, grouped_elgamal::GroupedElGamalCiphertext,
18 pedersen::PedersenOpening,
19 },
20 errors::{ProofGenerationError, ProofVerificationError},
21 sigma_proofs::grouped_ciphertext_validity_proof::GroupedCiphertext2HandlesValidityProof,
22 transcript::TranscriptProtocol,
23 },
24 merlin::Transcript,
25};
26use {
27 crate::{
28 instruction::{ProofType, ZkProofData},
29 zk_token_elgamal::pod,
30 },
31 bytemuck_derive::{Pod, Zeroable},
32};
33
34#[derive(Clone, Copy, Pod, Zeroable)]
40#[repr(C)]
41pub struct GroupedCiphertext2HandlesValidityProofData {
42 pub context: GroupedCiphertext2HandlesValidityProofContext,
43
44 pub proof: pod::GroupedCiphertext2HandlesValidityProof,
45}
46
47#[derive(Clone, Copy, Pod, Zeroable)]
48#[repr(C)]
49pub struct GroupedCiphertext2HandlesValidityProofContext {
50 pub destination_pubkey: pod::ElGamalPubkey, pub auditor_pubkey: pod::ElGamalPubkey, pub grouped_ciphertext: pod::GroupedElGamalCiphertext2Handles, }
56
57#[cfg(not(target_os = "solana"))]
58impl GroupedCiphertext2HandlesValidityProofData {
59 pub fn new(
60 destination_pubkey: &ElGamalPubkey,
61 auditor_pubkey: &ElGamalPubkey,
62 grouped_ciphertext: &GroupedElGamalCiphertext<2>,
63 amount: u64,
64 opening: &PedersenOpening,
65 ) -> Result<Self, ProofGenerationError> {
66 let pod_destination_pubkey = pod::ElGamalPubkey(destination_pubkey.into());
67 let pod_auditor_pubkey = pod::ElGamalPubkey(auditor_pubkey.into());
68 let pod_grouped_ciphertext = (*grouped_ciphertext).into();
69
70 let context = GroupedCiphertext2HandlesValidityProofContext {
71 destination_pubkey: pod_destination_pubkey,
72 auditor_pubkey: pod_auditor_pubkey,
73 grouped_ciphertext: pod_grouped_ciphertext,
74 };
75
76 let mut transcript = context.new_transcript();
77
78 let proof = GroupedCiphertext2HandlesValidityProof::new(
79 (destination_pubkey, auditor_pubkey),
80 amount,
81 opening,
82 &mut transcript,
83 )
84 .into();
85
86 Ok(Self { context, proof })
87 }
88}
89
90impl ZkProofData<GroupedCiphertext2HandlesValidityProofContext>
91 for GroupedCiphertext2HandlesValidityProofData
92{
93 const PROOF_TYPE: ProofType = ProofType::GroupedCiphertext2HandlesValidity;
94
95 fn context_data(&self) -> &GroupedCiphertext2HandlesValidityProofContext {
96 &self.context
97 }
98
99 #[cfg(not(target_os = "solana"))]
100 fn verify_proof(&self) -> Result<(), ProofVerificationError> {
101 let mut transcript = self.context.new_transcript();
102
103 let destination_pubkey = self.context.destination_pubkey.try_into()?;
104 let auditor_pubkey = self.context.auditor_pubkey.try_into()?;
105 let grouped_ciphertext: GroupedElGamalCiphertext<2> =
106 self.context.grouped_ciphertext.try_into()?;
107
108 let destination_handle = grouped_ciphertext.handles.first().unwrap();
109 let auditor_handle = grouped_ciphertext.handles.get(1).unwrap();
110
111 let proof: GroupedCiphertext2HandlesValidityProof = self.proof.try_into()?;
112
113 proof
114 .verify(
115 &grouped_ciphertext.commitment,
116 (&destination_pubkey, &auditor_pubkey),
117 (destination_handle, auditor_handle),
118 &mut transcript,
119 )
120 .map_err(|e| e.into())
121 }
122}
123
124#[cfg(not(target_os = "solana"))]
125impl GroupedCiphertext2HandlesValidityProofContext {
126 fn new_transcript(&self) -> Transcript {
127 let mut transcript = Transcript::new(b"CiphertextValidityProof");
128
129 transcript.append_pubkey(b"destination-pubkey", &self.destination_pubkey);
130 transcript.append_pubkey(b"auditor-pubkey", &self.auditor_pubkey);
131 transcript
132 .append_grouped_ciphertext_2_handles(b"grouped-ciphertext", &self.grouped_ciphertext);
133
134 transcript
135 }
136}
137
138#[cfg(test)]
139mod test {
140 use {
141 super::*,
142 crate::encryption::{elgamal::ElGamalKeypair, grouped_elgamal::GroupedElGamal},
143 };
144
145 #[test]
146 fn test_ciphertext_validity_proof_instruction_correctness() {
147 let destination_keypair = ElGamalKeypair::new_rand();
148 let destination_pubkey = destination_keypair.pubkey();
149
150 let auditor_keypair = ElGamalKeypair::new_rand();
151 let auditor_pubkey = auditor_keypair.pubkey();
152
153 let amount: u64 = 55;
154 let opening = PedersenOpening::new_rand();
155 let grouped_ciphertext =
156 GroupedElGamal::encrypt_with([destination_pubkey, auditor_pubkey], amount, &opening);
157
158 let proof_data = GroupedCiphertext2HandlesValidityProofData::new(
159 destination_pubkey,
160 auditor_pubkey,
161 &grouped_ciphertext,
162 amount,
163 &opening,
164 )
165 .unwrap();
166
167 assert!(proof_data.verify_proof().is_ok());
168 }
169}