solana_zk_token_sdk/instruction/batched_grouped_ciphertext_validity/
handles_3.rs1#[cfg(not(target_os = "solana"))]
15use {
16 crate::{
17 encryption::{
18 elgamal::ElGamalPubkey, grouped_elgamal::GroupedElGamalCiphertext,
19 pedersen::PedersenOpening,
20 },
21 errors::{ProofGenerationError, ProofVerificationError},
22 sigma_proofs::batched_grouped_ciphertext_validity_proof::BatchedGroupedCiphertext3HandlesValidityProof,
23 transcript::TranscriptProtocol,
24 },
25 merlin::Transcript,
26};
27use {
28 crate::{
29 instruction::{ProofType, ZkProofData},
30 zk_token_elgamal::pod,
31 },
32 bytemuck_derive::{Pod, Zeroable},
33};
34
35#[derive(Clone, Copy, Pod, Zeroable)]
41#[repr(C)]
42pub struct BatchedGroupedCiphertext3HandlesValidityProofData {
43 pub context: BatchedGroupedCiphertext3HandlesValidityProofContext,
44
45 pub proof: pod::BatchedGroupedCiphertext3HandlesValidityProof,
46}
47
48#[derive(Clone, Copy, Pod, Zeroable)]
49#[repr(C)]
50pub struct BatchedGroupedCiphertext3HandlesValidityProofContext {
51 pub source_pubkey: pod::ElGamalPubkey, pub destination_pubkey: pod::ElGamalPubkey, pub auditor_pubkey: pod::ElGamalPubkey, pub grouped_ciphertext_lo: pod::GroupedElGamalCiphertext3Handles, pub grouped_ciphertext_hi: pod::GroupedElGamalCiphertext3Handles, }
61
62#[cfg(not(target_os = "solana"))]
63impl BatchedGroupedCiphertext3HandlesValidityProofData {
64 pub fn new(
65 source_pubkey: &ElGamalPubkey,
66 destination_pubkey: &ElGamalPubkey,
67 auditor_pubkey: &ElGamalPubkey,
68 grouped_ciphertext_lo: &GroupedElGamalCiphertext<3>,
69 grouped_ciphertext_hi: &GroupedElGamalCiphertext<3>,
70 amount_lo: u64,
71 amount_hi: u64,
72 opening_lo: &PedersenOpening,
73 opening_hi: &PedersenOpening,
74 ) -> Result<Self, ProofGenerationError> {
75 let pod_source_pubkey = pod::ElGamalPubkey(source_pubkey.into());
76 let pod_destination_pubkey = pod::ElGamalPubkey(destination_pubkey.into());
77 let pod_auditor_pubkey = pod::ElGamalPubkey(auditor_pubkey.into());
78 let pod_grouped_ciphertext_lo = (*grouped_ciphertext_lo).into();
79 let pod_grouped_ciphertext_hi = (*grouped_ciphertext_hi).into();
80
81 let context = BatchedGroupedCiphertext3HandlesValidityProofContext {
82 source_pubkey: pod_source_pubkey,
83 destination_pubkey: pod_destination_pubkey,
84 auditor_pubkey: pod_auditor_pubkey,
85 grouped_ciphertext_lo: pod_grouped_ciphertext_lo,
86 grouped_ciphertext_hi: pod_grouped_ciphertext_hi,
87 };
88
89 let mut transcript = context.new_transcript();
90
91 let proof = BatchedGroupedCiphertext3HandlesValidityProof::new(
92 source_pubkey,
93 destination_pubkey,
94 auditor_pubkey,
95 amount_lo,
96 amount_hi,
97 opening_lo,
98 opening_hi,
99 &mut transcript,
100 )
101 .into();
102
103 Ok(Self { context, proof })
104 }
105}
106
107impl ZkProofData<BatchedGroupedCiphertext3HandlesValidityProofContext>
108 for BatchedGroupedCiphertext3HandlesValidityProofData
109{
110 const PROOF_TYPE: ProofType = ProofType::BatchedGroupedCiphertext3HandlesValidity;
111
112 fn context_data(&self) -> &BatchedGroupedCiphertext3HandlesValidityProofContext {
113 &self.context
114 }
115
116 #[cfg(not(target_os = "solana"))]
117 fn verify_proof(&self) -> Result<(), ProofVerificationError> {
118 let mut transcript = self.context.new_transcript();
119
120 let source_pubkey = self.context.source_pubkey.try_into()?;
121 let destination_pubkey = self.context.destination_pubkey.try_into()?;
122 let auditor_pubkey = self.context.auditor_pubkey.try_into()?;
123 let grouped_ciphertext_lo: GroupedElGamalCiphertext<3> =
124 self.context.grouped_ciphertext_lo.try_into()?;
125 let grouped_ciphertext_hi: GroupedElGamalCiphertext<3> =
126 self.context.grouped_ciphertext_hi.try_into()?;
127
128 let source_handle_lo = grouped_ciphertext_lo.handles.first().unwrap();
129 let destination_handle_lo = grouped_ciphertext_lo.handles.get(1).unwrap();
130 let auditor_handle_lo = grouped_ciphertext_lo.handles.get(2).unwrap();
131
132 let source_handle_hi = grouped_ciphertext_hi.handles.first().unwrap();
133 let destination_handle_hi = grouped_ciphertext_hi.handles.get(1).unwrap();
134 let auditor_handle_hi = grouped_ciphertext_hi.handles.get(2).unwrap();
135
136 let proof: BatchedGroupedCiphertext3HandlesValidityProof = self.proof.try_into()?;
137
138 proof
139 .verify(
140 &source_pubkey,
141 &destination_pubkey,
142 &auditor_pubkey,
143 &grouped_ciphertext_lo.commitment,
144 &grouped_ciphertext_hi.commitment,
145 source_handle_lo,
146 source_handle_hi,
147 destination_handle_lo,
148 destination_handle_hi,
149 auditor_handle_lo,
150 auditor_handle_hi,
151 &mut transcript,
152 )
153 .map_err(|e| e.into())
154 }
155}
156
157#[cfg(not(target_os = "solana"))]
158impl BatchedGroupedCiphertext3HandlesValidityProofContext {
159 fn new_transcript(&self) -> Transcript {
160 let mut transcript = Transcript::new(b"BatchedGroupedCiphertext3HandlesValidityProof");
161
162 transcript.append_pubkey(b"source-pubkey", &self.source_pubkey);
163 transcript.append_pubkey(b"destination-pubkey", &self.destination_pubkey);
164 transcript.append_pubkey(b"auditor-pubkey", &self.auditor_pubkey);
165 transcript.append_grouped_ciphertext_3_handles(
166 b"grouped-ciphertext-lo",
167 &self.grouped_ciphertext_lo,
168 );
169 transcript.append_grouped_ciphertext_3_handles(
170 b"grouped-ciphertext-hi",
171 &self.grouped_ciphertext_hi,
172 );
173
174 transcript
175 }
176}
177
178#[cfg(test)]
179mod test {
180 use {
181 super::*,
182 crate::encryption::{elgamal::ElGamalKeypair, grouped_elgamal::GroupedElGamal},
183 };
184
185 #[test]
186 fn test_ciphertext_validity_proof_instruction_correctness() {
187 let source_keypair = ElGamalKeypair::new_rand();
188 let source_pubkey = source_keypair.pubkey();
189
190 let destination_keypair = ElGamalKeypair::new_rand();
191 let destination_pubkey = destination_keypair.pubkey();
192
193 let auditor_keypair = ElGamalKeypair::new_rand();
194 let auditor_pubkey = auditor_keypair.pubkey();
195
196 let amount_lo: u64 = 11;
197 let amount_hi: u64 = 22;
198
199 let opening_lo = PedersenOpening::new_rand();
200 let opening_hi = PedersenOpening::new_rand();
201
202 let grouped_ciphertext_lo = GroupedElGamal::encrypt_with(
203 [source_pubkey, destination_pubkey, auditor_pubkey],
204 amount_lo,
205 &opening_lo,
206 );
207
208 let grouped_ciphertext_hi = GroupedElGamal::encrypt_with(
209 [source_pubkey, destination_pubkey, auditor_pubkey],
210 amount_hi,
211 &opening_hi,
212 );
213
214 let proof_data = BatchedGroupedCiphertext3HandlesValidityProofData::new(
215 source_pubkey,
216 destination_pubkey,
217 auditor_pubkey,
218 &grouped_ciphertext_lo,
219 &grouped_ciphertext_hi,
220 amount_lo,
221 amount_hi,
222 &opening_lo,
223 &opening_hi,
224 )
225 .unwrap();
226
227 assert!(proof_data.verify_proof().is_ok());
228 }
229}