@@ -14,72 +14,90 @@ use sigma_rs::{
1414type G = RistrettoPoint ;
1515type ProofResult < T > = Result < T , Error > ;
1616
17+ /// Create an OR relation between two statements:
18+ /// 1. Knowledge of discrete log: P1 = x1 * G
19+ /// 2. Knowledge of DLEQ: (P2 = x2 * G, Q = x2 * H)
1720#[ allow( non_snake_case) ]
18- pub fn discrete_logarithm ( x : Scalar ) -> ( LinearRelation < G > , Vec < Scalar > ) {
19- let mut relation = LinearRelation :: < G > :: new ( ) ;
20-
21- let var_x = relation. allocate_scalar ( ) ;
22- let var_G = relation. allocate_element ( ) ;
23- let _var_X = relation. allocate_eq ( var_x * var_G) ;
24-
25- relation. set_element ( var_G, G :: generator ( ) ) ;
26- relation. compute_image ( & [ x] ) . unwrap ( ) ;
27-
28- ( relation, vec ! [ x] )
29- }
30-
31- #[ allow( non_snake_case) ]
32- pub fn dleq ( x : Scalar , h : G ) -> ( LinearRelation < G > , Vec < Scalar > ) {
33- let mut relation = LinearRelation :: < G > :: new ( ) ;
34-
35- let var_x = relation. allocate_scalar ( ) ;
36- let [ var_G, var_H] = relation. allocate_elements ( ) ;
37- let _var_X = relation. allocate_eq ( var_x * var_G) ;
38- let _var_Y = relation. allocate_eq ( var_x * var_H) ;
39-
40- relation. set_elements ( [ ( var_G, G :: generator ( ) ) , ( var_H, h) ] ) ;
41- relation. compute_image ( & [ x] ) . unwrap ( ) ;
42-
43- ( relation, vec ! [ x] )
44- }
45-
46- fn create_or_relations ( x1 : Scalar , x2 : Scalar , h : G ) -> ( Protocol < G > , ProtocolWitness < G > ) {
47- let ( rel1, _) = discrete_logarithm ( x1) ;
48- let ( rel2, witness2) = dleq ( x2, h) ;
49-
21+ fn create_relation ( P1 : G , P2 : G , Q : G , H : G ) -> Protocol < G > {
22+ // First relation: discrete logarithm P1 = x1 * G
23+ let mut rel1 = LinearRelation :: < G > :: new ( ) ;
24+ let x1 = rel1. allocate_scalar ( ) ;
25+ let G1 = rel1. allocate_element ( ) ;
26+ let P1_var = rel1. allocate_eq ( x1 * G1 ) ;
27+ rel1. set_element ( G1 , G :: generator ( ) ) ;
28+ rel1. set_element ( P1_var , P1 ) ;
29+
30+ // Second relation: DLEQ (P2 = x2 * G, Q = x2 * H)
31+ let mut rel2 = LinearRelation :: < G > :: new ( ) ;
32+ let x2 = rel2. allocate_scalar ( ) ;
33+ let G2 = rel2. allocate_element ( ) ;
34+ let H_var = rel2. allocate_element ( ) ;
35+ let P2_var = rel2. allocate_eq ( x2 * G2 ) ;
36+ let Q_var = rel2. allocate_eq ( x2 * H_var ) ;
37+ rel2. set_element ( G2 , G :: generator ( ) ) ;
38+ rel2. set_element ( H_var , H ) ;
39+ rel2. set_element ( P2_var , P2 ) ;
40+ rel2. set_element ( Q_var , Q ) ;
41+
42+ // Compose into OR protocol
5043 let proto1 = Protocol :: from ( rel1) ;
5144 let proto2 = Protocol :: from ( rel2) ;
52- let composed = Protocol :: Or ( vec ! [ proto1, proto2] ) ;
53-
54- let witness = ProtocolWitness :: Or ( 1 , vec ! [ ProtocolWitness :: Simple ( witness2) ] ) ;
55-
56- ( composed, witness)
45+ Protocol :: Or ( vec ! [ proto1, proto2] )
5746}
5847
59- fn prove_or ( x1 : Scalar , x2 : Scalar , h : G ) -> ProofResult < Vec < u8 > > {
48+ /// Prove knowledge of one of the witnesses (we know x2 for the DLEQ)
49+ #[ allow( non_snake_case) ]
50+ fn prove ( P1 : G , x2 : Scalar , H : G ) -> ProofResult < Vec < u8 > > {
6051 let mut rng = OsRng ;
61- let ( composed, witness) = create_or_relations ( x1, x2, h) ;
62- let nizk = NISigmaProtocol :: < _ , ShakeCodec < G > > :: new ( b"or_proof_example" , composed) ;
52+
53+ // Compute public values
54+ let P2 = G :: generator ( ) * x2;
55+ let Q = H * x2;
56+
57+ let protocol = create_relation ( P1 , P2 , Q , H ) ;
58+ let witness = ProtocolWitness :: Or ( 1 , vec ! [ ProtocolWitness :: Simple ( vec![ x2] ) ] ) ;
59+ let nizk = NISigmaProtocol :: < _ , ShakeCodec < G > > :: new ( b"or_proof_example" , protocol) ;
6360
6461 nizk. prove_batchable ( & witness, & mut rng)
6562}
6663
67- fn verify_or ( x1 : Scalar , x2 : Scalar , h : G , proof : & [ u8 ] ) -> ProofResult < ( ) > {
68- let ( composed, _) = create_or_relations ( x1, x2, h) ;
69- let nizk = NISigmaProtocol :: < _ , ShakeCodec < G > > :: new ( b"or_proof_example" , composed) ;
64+ /// Verify an OR proof given the public values
65+ #[ allow( non_snake_case) ]
66+ fn verify ( P1 : G , P2 : G , Q : G , H : G , proof : & [ u8 ] ) -> ProofResult < ( ) > {
67+ let protocol = create_relation ( P1 , P2 , Q , H ) ;
68+ let nizk = NISigmaProtocol :: < _ , ShakeCodec < G > > :: new ( b"or_proof_example" , protocol) ;
7069
7170 nizk. verify_batchable ( proof)
7271}
7372
73+ #[ allow( non_snake_case) ]
7474fn main ( ) {
7575 let mut rng = OsRng ;
76+
77+ // Setup: We don't know x1, but we do know x2
7678 let x1 = Scalar :: random ( & mut rng) ;
7779 let x2 = Scalar :: random ( & mut rng) ;
78- let h = G :: random ( & mut rng) ;
79-
80- let proof = prove_or ( x1, x2, h) . expect ( "Proof generation failed" ) ;
81- let verified = verify_or ( x1, x2, h, & proof) . is_ok ( ) ;
82-
83- println ! ( "OR-proof verified: {verified}" ) ;
84- println ! ( "Proof bytes: {}" , hex:: encode( & proof) ) ;
80+ let H = G :: random ( & mut rng) ;
81+
82+ // Compute public values
83+ let P1 = G :: generator ( ) * x1; // We don't actually know x1 in the proof
84+ let P2 = G :: generator ( ) * x2; // We know x2
85+ let Q = H * x2; // Q = x2 * H
86+
87+ println ! ( "OR-proof example: Proving knowledge of x1 OR x2" ) ;
88+ println ! ( "(We only know x2, not x1)" ) ;
89+
90+ match prove ( P1 , x2, H ) {
91+ Ok ( proof) => {
92+ println ! ( "Proof generated successfully" ) ;
93+ println ! ( "Proof (hex): {}" , hex:: encode( & proof) ) ;
94+
95+ // Verify the proof
96+ match verify ( P1 , P2 , Q , H , & proof) {
97+ Ok ( ( ) ) => println ! ( "✓ Proof verified successfully!" ) ,
98+ Err ( e) => println ! ( "✗ Proof verification failed: {:?}" , e) ,
99+ }
100+ }
101+ Err ( e) => println ! ( "✗ Failed to generate proof: {:?}" , e) ,
102+ }
85103}
0 commit comments