1818//! )
1919//! ```
2020
21- use core:: error;
22-
2321use ff:: { Field , PrimeField } ;
2422use group:: prime:: PrimeGroup ;
2523use sha3:: Digest ;
@@ -83,11 +81,12 @@ pub enum ComposedCommitment<G: PrimeGroup> {
8381pub enum ComposedProverState < G : PrimeGroup > {
8482 Simple ( <SchnorrProof < G > as SigmaProtocol >:: ProverState ) ,
8583 And ( Vec < ComposedProverState < G > > ) ,
86- Or (
87- Vec < CtOption < ComposedProverState < G > > > , // all states (real and dummy)
88- Vec < CtOption < ComposedChallenge < G > > > , // all challenges
89- Vec < CtOption < ComposedResponse < G > > > , // all responses
90- ) ,
84+ Or {
85+ real_index : CtOption < u64 > ,
86+ states : Vec < ComposedProverState < G > > ,
87+ challenges : Vec < ComposedChallenge < G > > ,
88+ responses : Vec < ComposedResponse < G > > ,
89+ } ,
9190}
9291
9392// Structure representing the Response type of Protocol as SigmaProtocol
@@ -99,6 +98,7 @@ pub enum ComposedResponse<G: PrimeGroup> {
9998}
10099
101100// Structure representing the Witness type of Protocol as SigmaProtocol
101+ #[ derive( Clone ) ]
102102pub enum ComposedWitness < G : PrimeGroup > {
103103 Simple ( <SchnorrProof < G > as SigmaProtocol >:: Witness ) ,
104104 And ( Vec < ComposedWitness < G > > ) ,
@@ -109,8 +109,8 @@ pub enum ComposedWitness<G: PrimeGroup> {
109109type ComposedChallenge < G > = <SchnorrProof < G > as SigmaProtocol >:: Challenge ;
110110
111111impl < G : PrimeGroup > ComposedRelation < G > {
112- /// Handle the Simple case for prover_commit
113- fn prover_commit_simple (
112+ // Private helper methods for Simple case
113+ fn prover_commit_simple_impl (
114114 protocol : & SchnorrProof < G > ,
115115 witness : & <SchnorrProof < G > as SigmaProtocol >:: Witness ,
116116 rng : & mut ( impl rand:: Rng + rand:: CryptoRng ) ,
@@ -123,8 +123,7 @@ impl<G: PrimeGroup> ComposedRelation<G> {
123123 } )
124124 }
125125
126- /// Handle the Simple case for prover_response
127- fn prover_response_simple (
126+ fn prover_response_simple_impl (
128127 protocol : & SchnorrProof < G > ,
129128 state : <SchnorrProof < G > as SigmaProtocol >:: ProverState ,
130129 challenge : & <SchnorrProof < G > as SigmaProtocol >:: Challenge ,
@@ -134,8 +133,8 @@ impl<G: PrimeGroup> ComposedRelation<G> {
134133 . map ( ComposedResponse :: Simple )
135134 }
136135
137- /// Handle the And case for prover_commit
138- fn prover_commit_and (
136+ // Private helper methods for And case
137+ fn prover_commit_and_impl (
139138 protocols : & [ ComposedRelation < G > ] ,
140139 witnesses : & [ ComposedWitness < G > ] ,
141140 rng : & mut ( impl rand:: Rng + rand:: CryptoRng ) ,
@@ -159,8 +158,7 @@ impl<G: PrimeGroup> ComposedRelation<G> {
159158 ) )
160159 }
161160
162- /// Handle the And case for prover_response
163- fn prover_response_and (
161+ fn prover_response_and_impl (
164162 protocols : & [ ComposedRelation < G > ] ,
165163 states : Vec < ComposedProverState < G > > ,
166164 challenge : & ComposedChallenge < G > ,
@@ -178,8 +176,8 @@ impl<G: PrimeGroup> ComposedRelation<G> {
178176 Ok ( ComposedResponse :: And ( responses?) )
179177 }
180178
181- /// Handle the Or case for prover_commit
182- fn prover_commit_or (
179+ // Private helper methods for Or case
180+ fn prover_commit_or_impl (
183181 protocols : & [ ComposedRelation < G > ] ,
184182 witnesses : & [ CtOption < ComposedWitness < G > > ] ,
185183 rng : & mut ( impl rand:: Rng + rand:: CryptoRng ) ,
@@ -188,73 +186,174 @@ impl<G: PrimeGroup> ComposedRelation<G> {
188186 return Err ( Error :: InvalidInstanceWitnessPair ) ;
189187 }
190188
191- let mut commitments = Vec :: with_capacity ( protocols. len ( ) ) ;
192- let mut real_state = None ;
193- let mut real_index = None ;
194- let mut simulated_challenges = Vec :: new ( ) ;
195- let mut simulated_responses = Vec :: new ( ) ;
196-
197- // Process each witness using constant-time operations
198- for ( p, w_opt) in protocols. iter ( ) . zip ( witnesses. iter ( ) ) {
199- // Use map and or_else for constant-time branching
200- let state = w_opt
201- . map ( |w| {
202- let ( commitment, state) = p. prover_commit ( & w, rng) . unwrap ( ) ;
189+ // Find which witness is real (if any)
190+ let mut real_idx = None ;
191+ for ( i, w_opt) in witnesses. iter ( ) . enumerate ( ) {
192+ if w_opt. is_some ( ) . unwrap_u8 ( ) == 1 {
193+ real_idx = Some ( i) ;
194+ break ;
195+ }
196+ }
203197
198+ let mut commitments = Vec :: with_capacity ( protocols. len ( ) ) ;
199+ let mut states = Vec :: with_capacity ( protocols. len ( ) ) ;
200+ let mut challenges = Vec :: with_capacity ( protocols. len ( ) ) ;
201+ let mut responses = Vec :: with_capacity ( protocols. len ( ) ) ;
204202
205- } )
206- . unwrap_or_else ( || p. simulate_transcript ( rng) . unwrap ( ) ) ;
203+ // Process each protocol
204+ for ( i, p) in protocols. iter ( ) . enumerate ( ) {
205+ if real_idx == Some ( i) {
206+ // Real case: generate commitment and state
207+ // Use a separate function to handle the witness extraction
208+ // For the real witness, we need to clone it to avoid moving from borrowed reference
209+ let w = witnesses[ i] . clone ( ) . unwrap ( ) ;
210+ let ( c, s) = p. prover_commit ( & w, rng) ?;
211+ commitments. push ( c) ;
212+ states. push ( s) ;
213+ challenges. push ( G :: Scalar :: ZERO ) ;
214+ responses. push ( p. simulate_response ( rng) ) ;
215+ } else {
216+ // Simulated case: generate full transcript
217+ let ( c, ch, r) = p. simulate_transcript ( rng) ?;
218+ commitments. push ( c) ;
219+ // Create a dummy state
220+ let dummy_state = match p {
221+ ComposedRelation :: Simple ( _) => ComposedProverState :: Simple ( ( vec ! [ ] , vec ! [ ] ) ) ,
222+ ComposedRelation :: And ( _) => ComposedProverState :: And ( vec ! [ ] ) ,
223+ ComposedRelation :: Or ( _) => ComposedProverState :: Or {
224+ real_index : CtOption :: new ( 0u64 , 0u8 . into ( ) ) ,
225+ states : vec ! [ ] ,
226+ challenges : vec ! [ ] ,
227+ responses : vec ! [ ] ,
228+ } ,
229+ } ;
230+ states. push ( dummy_state) ;
231+ challenges. push ( ch) ;
232+ responses. push ( r) ;
233+ }
207234 }
208235
209- let real_idx = real_index. ok_or ( Error :: InvalidInstanceWitnessPair ) ?;
210- let real_prover_state = real_state. ok_or ( Error :: InvalidInstanceWitnessPair ) ?;
211-
212236 Ok ( (
213237 ComposedCommitment :: Or ( commitments) ,
214- ComposedProverState :: Or (
215- real_idx,
216- vec ! [ real_prover_state] ,
217- ( simulated_challenges, simulated_responses) ,
218- ) ,
238+ ComposedProverState :: Or {
239+ real_index : CtOption :: new (
240+ real_idx. map ( |i| i as u64 ) . unwrap_or ( 0 ) ,
241+ if real_idx. is_some ( ) {
242+ 1u8 . into ( )
243+ } else {
244+ 0u8 . into ( )
245+ } ,
246+ ) ,
247+ states,
248+ challenges,
249+ responses,
250+ } ,
219251 ) )
220252 }
221253
222- /// Handle the Or case for prover_response
223- fn prover_response_or (
254+ fn prover_response_or_impl (
224255 protocols : & [ ComposedRelation < G > ] ,
225- states : Vec < CtOption < ComposedProverState < G > > > ,
226- all_challenges : Vec < ComposedChallenge < G > > ,
227- all_responses : Vec < ComposedResponse < G > > ,
256+ real_index : CtOption < u64 > ,
257+ states : Vec < ComposedProverState < G > > ,
258+ pre_challenges : Vec < ComposedChallenge < G > > ,
259+ pre_responses : Vec < ComposedResponse < G > > ,
228260 challenge : & ComposedChallenge < G > ,
229261 ) -> Result < ComposedResponse < G > , Error > {
230- let mut challenges = Vec :: with_capacity ( protocols. len ( ) ) ;
231- let mut responses = Vec :: with_capacity ( protocols. len ( ) ) ;
262+ let mut final_challenges = Vec :: with_capacity ( protocols. len ( ) ) ;
263+ let mut final_responses = Vec :: with_capacity ( protocols. len ( ) ) ;
232264
233265 // Calculate the real challenge by subtracting all simulated challenges
234266 let mut real_challenge = * challenge;
235- for ch in & all_challenges {
236- real_challenge -= ch;
237- }
267+ let real_idx_value = if real_index. is_some ( ) . unwrap_u8 ( ) == 1 {
268+ let idx = real_index. unwrap ( ) as usize ;
269+ for ( i, ch) in pre_challenges. iter ( ) . enumerate ( ) {
270+ if i != idx {
271+ real_challenge -= ch;
272+ }
273+ }
274+ Some ( idx)
275+ } else {
276+ None
277+ } ;
238278
239279 // Process each protocol
240- for ( i, ( p, state_opt) ) in protocols. iter ( ) . zip ( states. iter ( ) ) . enumerate ( ) {
241- // Use constant-time selection to determine if this is the real or simulated case
242- let ( ch, resp) = state_opt
243- . map ( |state| {
244- // Real case: compute response with real challenge
245- let resp = p. prover_response ( state, & real_challenge) . unwrap ( ) ;
246- ( real_challenge, resp)
247- } )
248- . unwrap_or_else ( || {
249- // Simulated case: use pre-computed challenge and response
250- ( all_challenges[ i] , all_responses[ i] . clone ( ) )
251- } ) ;
252-
253- challenges. push ( ch) ;
254- responses. push ( resp) ;
280+ for ( i, p) in protocols. iter ( ) . enumerate ( ) {
281+ if real_idx_value == Some ( i) {
282+ // Real case: compute response with real challenge
283+ let resp = p. prover_response ( states[ i] . clone ( ) , & real_challenge) ?;
284+ final_challenges. push ( real_challenge) ;
285+ final_responses. push ( resp) ;
286+ } else {
287+ // Simulated case: use pre-computed values
288+ final_challenges. push ( pre_challenges[ i] ) ;
289+ final_responses. push ( pre_responses[ i] . clone ( ) ) ;
290+ }
255291 }
256292
257- Ok ( ComposedResponse :: Or ( challenges, responses) )
293+ Ok ( ComposedResponse :: Or ( final_challenges, final_responses) )
294+ }
295+ /// Handle the Simple case for prover_commit
296+ fn prover_commit_simple (
297+ protocol : & SchnorrProof < G > ,
298+ witness : & <SchnorrProof < G > as SigmaProtocol >:: Witness ,
299+ rng : & mut ( impl rand:: Rng + rand:: CryptoRng ) ,
300+ ) -> Result < ( ComposedCommitment < G > , ComposedProverState < G > ) , Error > {
301+ Self :: prover_commit_simple_impl ( protocol, witness, rng)
302+ }
303+
304+ /// Handle the Simple case for prover_response
305+ fn prover_response_simple (
306+ protocol : & SchnorrProof < G > ,
307+ state : <SchnorrProof < G > as SigmaProtocol >:: ProverState ,
308+ challenge : & <SchnorrProof < G > as SigmaProtocol >:: Challenge ,
309+ ) -> Result < ComposedResponse < G > , Error > {
310+ Self :: prover_response_simple_impl ( protocol, state, challenge)
311+ }
312+
313+ /// Handle the And case for prover_commit
314+ fn prover_commit_and (
315+ protocols : & [ ComposedRelation < G > ] ,
316+ witnesses : & [ ComposedWitness < G > ] ,
317+ rng : & mut ( impl rand:: Rng + rand:: CryptoRng ) ,
318+ ) -> Result < ( ComposedCommitment < G > , ComposedProverState < G > ) , Error > {
319+ Self :: prover_commit_and_impl ( protocols, witnesses, rng)
320+ }
321+
322+ /// Handle the And case for prover_response
323+ fn prover_response_and (
324+ protocols : & [ ComposedRelation < G > ] ,
325+ states : Vec < ComposedProverState < G > > ,
326+ challenge : & ComposedChallenge < G > ,
327+ ) -> Result < ComposedResponse < G > , Error > {
328+ Self :: prover_response_and_impl ( protocols, states, challenge)
329+ }
330+
331+ /// Handle the Or case for prover_commit
332+ fn prover_commit_or (
333+ protocols : & [ ComposedRelation < G > ] ,
334+ witnesses : & [ CtOption < ComposedWitness < G > > ] ,
335+ rng : & mut ( impl rand:: Rng + rand:: CryptoRng ) ,
336+ ) -> Result < ( ComposedCommitment < G > , ComposedProverState < G > ) , Error > {
337+ Self :: prover_commit_or_impl ( protocols, witnesses, rng)
338+ }
339+
340+ /// Handle the Or case for prover_response
341+ fn prover_response_or (
342+ protocols : & [ ComposedRelation < G > ] ,
343+ real_index : CtOption < u64 > ,
344+ states : Vec < ComposedProverState < G > > ,
345+ pre_challenges : Vec < ComposedChallenge < G > > ,
346+ pre_responses : Vec < ComposedResponse < G > > ,
347+ challenge : & ComposedChallenge < G > ,
348+ ) -> Result < ComposedResponse < G > , Error > {
349+ Self :: prover_response_or_impl (
350+ protocols,
351+ real_index,
352+ states,
353+ pre_challenges,
354+ pre_responses,
355+ challenge,
356+ )
258357 }
259358}
260359
@@ -298,8 +397,13 @@ impl<G: PrimeGroup> SigmaProtocol for ComposedRelation<G> {
298397 }
299398 (
300399 ComposedRelation :: Or ( ps) ,
301- ComposedProverState :: Or ( states, challenges, responses) ,
302- ) => Self :: prover_response_or ( ps, states, challenges, responses, challenge) ,
400+ ComposedProverState :: Or {
401+ real_index,
402+ states,
403+ challenges,
404+ responses,
405+ } ,
406+ ) => Self :: prover_response_or ( ps, real_index, states, challenges, responses, challenge) ,
303407 _ => Err ( Error :: InvalidInstanceWitnessPair ) ,
304408 }
305409 }
0 commit comments