1- //! Implementation of a structure [`Protocol`] aimed at generalizing the [`SchnorrProof`]
2- //! using the compositions of the latter via AND and OR links
1+ //! # Protocol Composition with AND/OR Logic
32//!
4- //! This structure allows, for example, the construction of protocols of the form:
3+ //! This module defines the [`Protocol`] enum, which generalizes the [`SchnorrProof`]
4+ //! by enabling compositional logic between multiple proof instances.
5+ //!
6+ //! Specifically, it supports:
7+ //! - Simple atomic proofs (e.g., discrete logarithm, Pedersen commitments)
8+ //! - Conjunctions (`And`) of multiple sub-protocols
9+ //! - Disjunctions (`Or`) of multiple sub-protocols
10+ //!
11+ //! ## Example Composition
12+ //!
13+ //! ```ignore
514//! And(
615//! Or( dleq, pedersen_commitment ),
716//! Simple( discrete_logarithm ),
817//! And( pedersen_commitment_dleq, bbs_blind_commitment_computation )
918//! )
19+ //! ```
1020
1121use ff:: { Field , PrimeField } ;
1222use group:: { Group , GroupEncoding } ;
@@ -104,11 +114,12 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
104114 ) -> Result < ( Self :: Commitment , Self :: ProverState ) , Error > {
105115 match ( self , witness) {
106116 ( Protocol :: Simple ( p) , ProtocolWitness :: Simple ( w) ) => {
107- let ( c, s) = p. prover_commit ( w, rng) ?;
108- Ok ( (
109- ProtocolCommitment :: Simple ( c) ,
110- ProtocolProverState :: Simple ( s) ,
111- ) )
117+ p. prover_commit ( w, rng) . map ( |( c, s) | {
118+ (
119+ ProtocolCommitment :: Simple ( c) ,
120+ ProtocolProverState :: Simple ( s) ,
121+ )
122+ } )
112123 }
113124 ( Protocol :: And ( ps) , ProtocolWitness :: And ( ws) ) => {
114125 if ps. len ( ) != ws. len ( ) {
@@ -162,20 +173,20 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
162173 challenge : & Self :: Challenge ,
163174 ) -> Result < Self :: Response , Error > {
164175 match ( self , state) {
165- ( Protocol :: Simple ( p) , ProtocolProverState :: Simple ( state) ) => {
166- let response = p. prover_response ( state, challenge) ?;
167- Ok ( ProtocolResponse :: Simple ( response) )
168- }
176+ ( Protocol :: Simple ( p) , ProtocolProverState :: Simple ( state) ) => p
177+ . prover_response ( state, challenge)
178+ . map ( ProtocolResponse :: Simple ) ,
169179 ( Protocol :: And ( ps) , ProtocolProverState :: And ( states) ) => {
170180 if ps. len ( ) != states. len ( ) {
171181 return Err ( Error :: InvalidInstanceWitnessPair ) ;
172182 }
173- let mut responses = Vec :: with_capacity ( ps. len ( ) ) ;
174- for ( i, p) in ps. iter ( ) . enumerate ( ) {
175- let r = p. prover_response ( states[ i] . clone ( ) , challenge) ?;
176- responses. push ( r) ;
177- }
178- Ok ( ProtocolResponse :: And ( responses) )
183+ let responses: Result < Vec < _ > , _ > = ps
184+ . iter ( )
185+ . zip ( states)
186+ . map ( |( p, s) | p. prover_response ( s, challenge) )
187+ . collect ( ) ;
188+
189+ Ok ( ProtocolResponse :: And ( responses?) )
179190 }
180191 (
181192 Protocol :: Or ( ps) ,
@@ -225,12 +236,11 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
225236 Protocol :: And ( ps) ,
226237 ProtocolCommitment :: And ( commitments) ,
227238 ProtocolResponse :: And ( responses) ,
228- ) => {
229- for ( i, p) in ps. iter ( ) . enumerate ( ) {
230- p. verifier ( & commitments[ i] , challenge, & responses[ i] ) ?;
231- }
232- Ok ( ( ) )
233- }
239+ ) => ps
240+ . iter ( )
241+ . zip ( commitments)
242+ . zip ( responses)
243+ . try_for_each ( |( ( p, c) , r) | p. verifier ( c, challenge, r) ) ,
234244 (
235245 Protocol :: Or ( ps) ,
236246 ProtocolCommitment :: Or ( commitments) ,
@@ -253,20 +263,12 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
253263 fn serialize_commitment ( & self , commitment : & Self :: Commitment ) -> Vec < u8 > {
254264 match ( self , commitment) {
255265 ( Protocol :: Simple ( p) , ProtocolCommitment :: Simple ( c) ) => p. serialize_commitment ( c) ,
256- ( Protocol :: And ( ps) , ProtocolCommitment :: And ( commitments) ) => {
257- let mut bytes = Vec :: new ( ) ;
258- for ( i, p) in ps. iter ( ) . enumerate ( ) {
259- bytes. extend ( p. serialize_commitment ( & commitments[ i] ) ) ;
260- }
261- bytes
262- }
263- ( Protocol :: Or ( ps) , ProtocolCommitment :: Or ( commitments) ) => {
264- let mut bytes = Vec :: new ( ) ;
265- for ( i, p) in ps. iter ( ) . enumerate ( ) {
266- bytes. extend ( p. serialize_commitment ( & commitments[ i] ) ) ;
267- }
268- bytes
269- }
266+ ( Protocol :: And ( ps) , ProtocolCommitment :: And ( commitments) )
267+ | ( Protocol :: Or ( ps) , ProtocolCommitment :: Or ( commitments) ) => ps
268+ . iter ( )
269+ . zip ( commitments)
270+ . flat_map ( |( p, c) | p. serialize_commitment ( c) )
271+ . collect ( ) ,
270272 _ => panic ! ( ) ,
271273 }
272274 }
@@ -354,27 +356,22 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
354356 let c = p. deserialize_commitment ( data) ?;
355357 Ok ( ProtocolCommitment :: Simple ( c) )
356358 }
357- Protocol :: And ( ps) => {
358- let mut cursor = 0 ;
359- let mut commitments = Vec :: with_capacity ( ps. len ( ) ) ;
360- for p in ps {
361- let c = p. deserialize_commitment ( & data[ cursor..] ) ?;
362- let size = p. serialize_commitment ( & c) . len ( ) ;
363- cursor += size;
364- commitments. push ( c) ;
365- }
366- Ok ( ProtocolCommitment :: And ( commitments) )
367- }
368- Protocol :: Or ( ps) => {
359+ Protocol :: And ( ps) | Protocol :: Or ( ps) => {
369360 let mut cursor = 0 ;
370361 let mut commitments = Vec :: with_capacity ( ps. len ( ) ) ;
362+
371363 for p in ps {
372364 let c = p. deserialize_commitment ( & data[ cursor..] ) ?;
373365 let size = p. serialize_commitment ( & c) . len ( ) ;
374366 cursor += size;
375367 commitments. push ( c) ;
376368 }
377- Ok ( ProtocolCommitment :: Or ( commitments) )
369+
370+ Ok ( match self {
371+ Protocol :: And ( _) => ProtocolCommitment :: And ( commitments) ,
372+ Protocol :: Or ( _) => ProtocolCommitment :: Or ( commitments) ,
373+ _ => unreachable ! ( ) ,
374+ } )
378375 }
379376 }
380377 }
@@ -436,17 +433,20 @@ impl<G: Group + GroupEncoding> SigmaProtocolSimulator for Protocol<G> {
436433 p. simulate_commitment ( challenge, r) ?,
437434 ) ) ,
438435 ( Protocol :: And ( ps) , ProtocolResponse :: And ( rs) ) => {
439- let mut commitments = Vec :: with_capacity ( ps. len ( ) ) ;
440- for ( i, p) in ps. iter ( ) . enumerate ( ) {
441- commitments. push ( p. simulate_commitment ( challenge, & rs[ i] ) ?) ;
442- }
436+ let commitments = ps
437+ . iter ( )
438+ . zip ( rs)
439+ . map ( |( p, r) | p. simulate_commitment ( challenge, r) )
440+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
443441 Ok ( ProtocolCommitment :: And ( commitments) )
444442 }
445- ( Protocol :: Or ( ps) , ProtocolResponse :: Or ( ch, rs) ) => {
446- let mut commitments = Vec :: with_capacity ( ps. len ( ) ) ;
447- for ( i, p) in ps. iter ( ) . enumerate ( ) {
448- commitments. push ( p. simulate_commitment ( & ch[ i] , & rs[ i] ) ?) ;
449- }
443+ ( Protocol :: Or ( ps) , ProtocolResponse :: Or ( challenges, rs) ) => {
444+ let commitments = ps
445+ . iter ( )
446+ . zip ( challenges)
447+ . zip ( rs)
448+ . map ( |( ( p, ch) , r) | p. simulate_commitment ( ch, r) )
449+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
450450 Ok ( ProtocolCommitment :: Or ( commitments) )
451451 }
452452 _ => panic ! ( ) ,
0 commit comments