2020
2121use ff:: { Field , PrimeField } ;
2222use group:: prime:: PrimeGroup ;
23- use sha3:: Digest ;
24- use sha3:: Sha3_256 ;
25- use subtle:: Choice ;
26- use subtle:: ConditionallySelectable ;
27- use subtle:: ConstantTimeEq ;
23+ use sha3:: { Digest , Sha3_256 } ;
24+ use subtle:: { Choice , ConditionallySelectable , ConstantTimeEq } ;
2825
26+ use crate :: errors:: InvalidInstance ;
2927use crate :: {
3028 codec:: Shake128DuplexSponge ,
3129 errors:: Error ,
@@ -48,18 +46,29 @@ pub enum ComposedRelation<G: PrimeGroup> {
4846 Or ( Vec < ComposedRelation < G > > ) ,
4947}
5048
49+ impl < G : PrimeGroup > ComposedRelation < G > {
50+ /// Create a [ComposedRelation] for an AND relation from the given list of relations.
51+ pub fn and < T : Into < ComposedRelation < G > > > ( witness : impl IntoIterator < Item = T > ) -> Self {
52+ Self :: And ( witness. into_iter ( ) . map ( |x| x. into ( ) ) . collect ( ) )
53+ }
54+
55+ /// Create a [ComposedRelation] for an OR relation from the given list of relations.
56+ pub fn or < T : Into < ComposedRelation < G > > > ( witness : impl IntoIterator < Item = T > ) -> Self {
57+ Self :: Or ( witness. into_iter ( ) . map ( |x| x. into ( ) ) . collect ( ) )
58+ }
59+ }
60+
5161impl < G : PrimeGroup > From < CanonicalLinearRelation < G > > for ComposedRelation < G > {
5262 fn from ( value : CanonicalLinearRelation < G > ) -> Self {
5363 ComposedRelation :: Simple ( value)
5464 }
5565}
5666
57- impl < G : PrimeGroup > From < LinearRelation < G > > for ComposedRelation < G > {
58- fn from ( value : LinearRelation < G > ) -> Self {
59- Self :: Simple (
60- CanonicalLinearRelation :: try_from ( value)
61- . expect ( "Failed to convert LinearRelation to CanonicalLinearRelation" ) ,
62- )
67+ impl < G : PrimeGroup > TryFrom < LinearRelation < G > > for ComposedRelation < G > {
68+ type Error = InvalidInstance ;
69+
70+ fn try_from ( value : LinearRelation < G > ) -> Result < Self , Self :: Error > {
71+ Ok ( Self :: Simple ( CanonicalLinearRelation :: try_from ( value) ?) )
6372 }
6473}
6574
@@ -102,6 +111,26 @@ pub enum ComposedWitness<G: PrimeGroup> {
102111 Or ( Vec < ComposedWitness < G > > ) ,
103112}
104113
114+ impl < G : PrimeGroup > ComposedWitness < G > {
115+ /// Create a [ComposedWitness] for an AND relation from the given list of witnesses.
116+ pub fn and < T : Into < ComposedWitness < G > > > ( witness : impl IntoIterator < Item = T > ) -> Self {
117+ Self :: And ( witness. into_iter ( ) . map ( |x| x. into ( ) ) . collect ( ) )
118+ }
119+
120+ /// Create a [ComposedWitness] for an OR relation from the given list of witnesses.
121+ pub fn or < T : Into < ComposedWitness < G > > > ( witness : impl IntoIterator < Item = T > ) -> Self {
122+ Self :: Or ( witness. into_iter ( ) . map ( |x| x. into ( ) ) . collect ( ) )
123+ }
124+ }
125+
126+ impl < G : PrimeGroup > From < <CanonicalLinearRelation < G > as SigmaProtocol >:: Witness >
127+ for ComposedWitness < G >
128+ {
129+ fn from ( value : <CanonicalLinearRelation < G > as SigmaProtocol >:: Witness ) -> Self {
130+ Self :: Simple ( value)
131+ }
132+ }
133+
105134type ComposedChallenge < G > = <CanonicalLinearRelation < G > as SigmaProtocol >:: Challenge ;
106135
107136const fn composed_challenge_size < G : PrimeGroup > ( ) -> usize {
@@ -207,37 +236,37 @@ impl<G: PrimeGroup + ConstantTimeEq> ComposedRelation<G> {
207236 let mut commitments = Vec :: new ( ) ;
208237 let mut prover_states = Vec :: new ( ) ;
209238
239+ // Selector value set when the first valid witness is found.
240+ let mut valid_witness_found = Choice :: from ( 0 ) ;
210241 for ( i, w) in witnesses. iter ( ) . enumerate ( ) {
211242 let ( commitment, prover_state) = instances[ i] . prover_commit ( w, rng) ?;
212243 let ( simulated_commitment, simulated_challenge, simulated_response) =
213244 instances[ i] . simulate_transcript ( rng) ?;
214245
246+ // TODO: Implement and use ConditionallySelectable here
215247 let valid_witness = instances[ i] . is_witness_valid ( w) ;
216- commitments. push ( if valid_witness. unwrap_u8 ( ) == 1 {
248+ let select_witness = valid_witness & !valid_witness_found;
249+ commitments. push ( if select_witness. unwrap_u8 ( ) == 1 {
217250 commitment
218251 } else {
219252 simulated_commitment. clone ( )
220253 } ) ;
221254 prover_states. push ( ComposedOrProverStateEntry (
222- valid_witness ,
255+ select_witness ,
223256 prover_state,
224257 simulated_challenge,
225258 simulated_response,
226259 ) ) ;
260+
261+ valid_witness_found |= valid_witness;
227262 }
228- // check that we have only one witness set
229- let witnesses_found = prover_states
230- . iter ( )
231- . map ( |x| x. 0 . unwrap_u8 ( ) as usize )
232- . sum :: < usize > ( ) ;
233- let prover_state = prover_states;
234263
235- if witnesses_found != 1 {
264+ if valid_witness_found . unwrap_u8 ( ) == 0 {
236265 Err ( Error :: InvalidInstanceWitnessPair )
237266 } else {
238267 Ok ( (
239268 ComposedCommitment :: Or ( commitments) ,
240- ComposedProverState :: Or ( prover_state ) ,
269+ ComposedProverState :: Or ( prover_states ) ,
241270 ) )
242271 }
243272 }
@@ -250,15 +279,13 @@ impl<G: PrimeGroup + ConstantTimeEq> ComposedRelation<G> {
250279 let mut result_challenges = Vec :: with_capacity ( instances. len ( ) ) ;
251280 let mut result_responses = Vec :: with_capacity ( instances. len ( ) ) ;
252281
253- let prover_states = prover_state;
254-
255282 let mut witness_challenge = * challenge;
256283 for ComposedOrProverStateEntry (
257284 valid_witness,
258285 _prover_state,
259286 simulated_challenge,
260287 _simulated_response,
261- ) in & prover_states
288+ ) in & prover_state
262289 {
263290 let c = G :: Scalar :: conditional_select (
264291 simulated_challenge,
@@ -275,7 +302,7 @@ impl<G: PrimeGroup + ConstantTimeEq> ComposedRelation<G> {
275302 simulated_challenge,
276303 simulated_response,
277304 ) ,
278- ) in instances. iter ( ) . zip ( prover_states )
305+ ) in instances. iter ( ) . zip ( prover_state )
279306 {
280307 let challenge_i = G :: Scalar :: conditional_select (
281308 & simulated_challenge,
0 commit comments