33
44use  curve25519_dalek:: ristretto:: CompressedRistretto ; 
55use  curve25519_dalek:: scalar:: Scalar ; 
6+ use  curve25519_dalek:: traits:: { Identity ,  IsIdentity } ; 
67
78use  errors:: R1CSError ; 
89use  inner_product_proof:: InnerProductProof ; 
@@ -11,6 +12,9 @@ use util;
1112use  serde:: de:: Visitor ; 
1213use  serde:: { self ,  Deserialize ,  Deserializer ,  Serialize ,  Serializer } ; 
1314
15+ const  ONE_PHASE_COMMITMENTS :  u8  = 0 ; 
16+ const  TWO_PHASE_COMMITMENTS :  u8  = 1 ; 
17+ 
1418/// A proof of some statement specified by a 
1519/// [`ConstraintSystem`](::r1cs::ConstraintSystem). 
1620/// 
@@ -64,25 +68,34 @@ pub struct R1CSProof {
6468} 
6569
6670impl  R1CSProof  { 
67-     /// Serializes the proof into a byte array of \\(16  + 2k\\) 32-byte elements, 
71+     /// Serializes the proof into a byte array of 1 version byte +  \\((13 or 16)  + 2k\\) 32-byte elements, 
6872     /// where \\(k=\lceil \log_2(n) \rceil\\) and \\(n\\) is the number of multiplication gates. 
6973     /// 
7074     /// # Layout 
7175     /// 
7276     /// The layout of the r1cs proof encoding is: 
73-      /// 
74-      /// * eleven compressed Ristretto points \\(A_{I1},A_{O1},S_1,A_{I2},A_{O2},S_2,T_1,...,T_6\\), 
77+      /// * 1 version byte indicating whether the proof contains second-phase commitments or not, 
78+      /// * 8 or 11 compressed Ristretto points \\(A_{I1},A_{O1},S_1,(A_{I2},A_{O2},S_2),T_1,...,T_6\\) 
79+      ///   (\\(A_{I2},A_{O2},S_2\\) are skipped if there were no multipliers added in the randomized phase), 
7580     /// * three scalars \\(t_x, \tilde{t}_x, \tilde{e}\\), 
7681     /// * \\(k\\) pairs of compressed Ristretto points \\(L_0,R_0\dots,L_{k-1},R_{k-1}\\), 
7782     /// * two scalars \\(a, b\\). 
7883     pub  fn  to_bytes ( & self )  -> Vec < u8 >  { 
7984        let  mut  buf = Vec :: with_capacity ( self . serialized_size ( ) ) ; 
80-         buf. extend_from_slice ( self . A_I1 . as_bytes ( ) ) ; 
81-         buf. extend_from_slice ( self . A_O1 . as_bytes ( ) ) ; 
82-         buf. extend_from_slice ( self . S1 . as_bytes ( ) ) ; 
83-         buf. extend_from_slice ( self . A_I2 . as_bytes ( ) ) ; 
84-         buf. extend_from_slice ( self . A_O2 . as_bytes ( ) ) ; 
85-         buf. extend_from_slice ( self . S2 . as_bytes ( ) ) ; 
85+         if  self . missing_phase2_commitments ( )  { 
86+             buf. push ( ONE_PHASE_COMMITMENTS ) ; 
87+             buf. extend_from_slice ( self . A_I1 . as_bytes ( ) ) ; 
88+             buf. extend_from_slice ( self . A_O1 . as_bytes ( ) ) ; 
89+             buf. extend_from_slice ( self . S1 . as_bytes ( ) ) ; 
90+         }  else  { 
91+             buf. push ( TWO_PHASE_COMMITMENTS ) ; 
92+             buf. extend_from_slice ( self . A_I1 . as_bytes ( ) ) ; 
93+             buf. extend_from_slice ( self . A_O1 . as_bytes ( ) ) ; 
94+             buf. extend_from_slice ( self . S1 . as_bytes ( ) ) ; 
95+             buf. extend_from_slice ( self . A_I2 . as_bytes ( ) ) ; 
96+             buf. extend_from_slice ( self . A_O2 . as_bytes ( ) ) ; 
97+             buf. extend_from_slice ( self . S2 . as_bytes ( ) ) ; 
98+         } 
8699        buf. extend_from_slice ( self . T_1 . as_bytes ( ) ) ; 
87100        buf. extend_from_slice ( self . T_3 . as_bytes ( ) ) ; 
88101        buf. extend_from_slice ( self . T_4 . as_bytes ( ) ) ; 
@@ -98,18 +111,40 @@ impl R1CSProof {
98111
99112    /// Returns the size in bytes required to serialize the `R1CSProof`. 
100113     pub  fn  serialized_size ( & self )  -> usize  { 
101-         // 14 elements + the ipp 
102-         14  *  32  + self . ipp_proof . serialized_size ( ) 
114+         // version tag + (11 or 14) elements + the ipp 
115+         let  elements = if  self . missing_phase2_commitments ( )  { 
116+             11 
117+         }  else  { 
118+             14 
119+         } ; 
120+         1  + elements *  32  + self . ipp_proof . serialized_size ( ) 
121+     } 
122+ 
123+     fn  missing_phase2_commitments ( & self )  -> bool  { 
124+         self . A_I2 . is_identity ( )  && self . A_O2 . is_identity ( )  && self . S2 . is_identity ( ) 
103125    } 
104126
105127    /// Deserializes the proof from a byte slice. 
106128     /// 
107129     /// Returns an error if the byte slice cannot be parsed into a `R1CSProof`. 
108-      pub  fn  from_bytes ( mut  slice :  & [ u8 ] )  -> Result < R1CSProof ,  R1CSError >  { 
130+      pub  fn  from_bytes ( slice :  & [ u8 ] )  -> Result < R1CSProof ,  R1CSError >  { 
131+         if  slice. len ( )  < 1  { 
132+             return  Err ( R1CSError :: FormatError ) ; 
133+         } 
134+         let  version = slice[ 0 ] ; 
135+         let  mut  slice = & slice[ 1 ..] ; 
136+ 
109137        if  slice. len ( )  % 32  != 0  { 
110138            return  Err ( R1CSError :: FormatError ) ; 
111139        } 
112-         if  slice. len ( )  < 14  *  32  { 
140+ 
141+         let  minlength = match  version { 
142+             ONE_PHASE_COMMITMENTS  => 11  *  32 , 
143+             TWO_PHASE_COMMITMENTS  => 14  *  32 , 
144+             _ => return  Err ( R1CSError :: FormatError ) , 
145+         } ; 
146+ 
147+         if  slice. len ( )  < minlength { 
113148            return  Err ( R1CSError :: FormatError ) ; 
114149        } 
115150
@@ -125,9 +160,19 @@ impl R1CSProof {
125160        let  A_I1  = CompressedRistretto ( read32 ! ( ) ) ; 
126161        let  A_O1  = CompressedRistretto ( read32 ! ( ) ) ; 
127162        let  S1  = CompressedRistretto ( read32 ! ( ) ) ; 
128-         let  A_I2  = CompressedRistretto ( read32 ! ( ) ) ; 
129-         let  A_O2  = CompressedRistretto ( read32 ! ( ) ) ; 
130-         let  S2  = CompressedRistretto ( read32 ! ( ) ) ; 
163+         let  ( A_I2 ,  A_O2 ,  S2 )  = if  version == ONE_PHASE_COMMITMENTS  { 
164+             ( 
165+                 CompressedRistretto :: identity ( ) , 
166+                 CompressedRistretto :: identity ( ) , 
167+                 CompressedRistretto :: identity ( ) , 
168+             ) 
169+         }  else  { 
170+             ( 
171+                 CompressedRistretto ( read32 ! ( ) ) , 
172+                 CompressedRistretto ( read32 ! ( ) ) , 
173+                 CompressedRistretto ( read32 ! ( ) ) , 
174+             ) 
175+         } ; 
131176        let  T_1  = CompressedRistretto ( read32 ! ( ) ) ; 
132177        let  T_3  = CompressedRistretto ( read32 ! ( ) ) ; 
133178        let  T_4  = CompressedRistretto ( read32 ! ( ) ) ; 
0 commit comments