@@ -186,10 +186,12 @@ mod instance_validation {
186186#[ cfg( test) ]
187187mod proof_validation {
188188 use crate :: codec:: KeccakByteSchnorrCodec ;
189+ use crate :: composition:: { ComposedRelation , ComposedWitness } ;
189190 use crate :: fiat_shamir:: Nizk ;
190191 use crate :: linear_relation:: { CanonicalLinearRelation , LinearRelation } ;
191192 use crate :: schnorr_protocol:: SchnorrProof ;
192193 use bls12_381:: { G1Projective as G , Scalar } ;
194+ use ff:: Field ;
193195 use rand:: { thread_rng, RngCore } ;
194196
195197 type TestNizk = Nizk < SchnorrProof < G > , KeccakByteSchnorrCodec < G > > ;
@@ -359,4 +361,75 @@ mod proof_validation {
359361 "Proof verification should fail for random bytes"
360362 ) ;
361363 }
364+
365+ #[ test]
366+ fn test_or_relation_wrong_branch ( ) {
367+ // This test reproduces the issue from sigma_compiler's simple_or test
368+ // where an OR relation fails verification when using the wrong branch
369+ let mut rng = thread_rng ( ) ;
370+
371+ // Create generators
372+ // For this test, we'll use two different multiples of the generator
373+ let B = G :: generator ( ) ;
374+ let A = B * Scalar :: from ( 42u64 ) ; // Different generator
375+
376+ // Create scalars
377+ let x = Scalar :: random ( & mut rng) ;
378+ let y = Scalar :: random ( & mut rng) ;
379+
380+ // Set C = y*B (so the second branch should be satisfied)
381+ let C = B * y;
382+
383+ // Create the first branch: C = x*A
384+ let mut lr1 = LinearRelation :: < G > :: new ( ) ;
385+ let x_var = lr1. allocate_scalar ( ) ;
386+ let A_var = lr1. allocate_element ( ) ;
387+ let eq1 = lr1. allocate_eq ( x_var * A_var ) ;
388+ lr1. set_element ( A_var , A ) ;
389+ lr1. set_element ( eq1, C ) ;
390+
391+ // Create the second branch: C = y*B
392+ let mut lr2 = LinearRelation :: < G > :: new ( ) ;
393+ let y_var = lr2. allocate_scalar ( ) ;
394+ let B_var = lr2. allocate_element ( ) ;
395+ let eq2 = lr2. allocate_eq ( y_var * B_var ) ;
396+ lr2. set_element ( B_var , B ) ;
397+ lr2. set_element ( eq2, C ) ;
398+
399+ // Create OR composition
400+ let or_relation = ComposedRelation :: Or ( vec ! [
401+ ComposedRelation :: from( lr1) ,
402+ ComposedRelation :: from( lr2) ,
403+ ] ) ;
404+
405+ // The issue from sigma_compiler: the witness is always using branch 0
406+ // even when branch 1 should be used
407+ let witness_wrong = ComposedWitness :: Or (
408+ 0 , // Always using branch 0
409+ vec ! [
410+ ComposedWitness :: Simple ( vec![ x] ) ,
411+ ComposedWitness :: Simple ( vec![ y] ) ,
412+ ] ,
413+ ) ;
414+
415+ // Test the bug: using branch 0 when C = y*B (branch 1 should be used)
416+ let nizk = Nizk :: < _ , KeccakByteSchnorrCodec < G > > :: new ( b"test_or_bug" , or_relation) ;
417+ let proof_result = nizk. prove_batchable ( & witness_wrong, & mut rng) ;
418+
419+ // This currently passes but should fail - this is the bug!
420+ // The prover is using branch 0 (C = x*A) but C actually equals y*B
421+ match proof_result {
422+ Ok ( proof) => {
423+ let verify_result = nizk. verify_batchable ( & proof) ;
424+ println ! ( "Bug reproduced: Proof with wrong branch verified: {:?}" , verify_result. is_ok( ) ) ;
425+ assert ! (
426+ verify_result. is_err( ) ,
427+ "BUG: Proof should fail when using wrong branch in OR relation, but it passed!"
428+ ) ;
429+ }
430+ Err ( e) => {
431+ println ! ( "Proof generation failed as expected: {:?}" , e) ;
432+ }
433+ }
434+ }
362435}
0 commit comments