@@ -11,6 +11,36 @@ use curve25519_dalek::traits::MultiscalarMul;
1111use digest:: { ExtendableOutput , Input , XofReader } ;
1212use sha3:: { Sha3XofReader , Shake256 } ;
1313
14+ /// Represents a pair of base points for Pedersen commitments.
15+ #[ derive( Copy , Clone ) ]
16+ pub struct PedersenGenerators {
17+ /// Base for the committed value
18+ pub B : RistrettoPoint ,
19+
20+ /// Base for the blinding factor
21+ pub B_blinding : RistrettoPoint ,
22+ }
23+
24+ impl PedersenGenerators {
25+ /// Creates a Pedersen commitment using the value scalar and a blinding factor.
26+ pub fn commit ( & self , value : Scalar , blinding : Scalar ) -> RistrettoPoint {
27+ RistrettoPoint :: multiscalar_mul ( & [ value, blinding] , & [ self . B , self . B_blinding ] )
28+ }
29+ }
30+
31+ impl Default for PedersenGenerators {
32+ fn default ( ) -> Self {
33+ PedersenGenerators {
34+ B : GeneratorsChain :: new ( b"Bulletproofs.Generators.B" )
35+ . next ( )
36+ . unwrap ( ) ,
37+ B_blinding : GeneratorsChain :: new ( b"Bulletproofs.Generators.B_blinding" )
38+ . next ( )
39+ . unwrap ( ) ,
40+ }
41+ }
42+ }
43+
1444/// The `GeneratorsChain` creates an arbitrary-long sequence of orthogonal generators.
1545/// The sequence can be deterministically produced starting with an arbitrary point.
1646struct GeneratorsChain {
@@ -55,107 +85,147 @@ impl Iterator for GeneratorsChain {
5585/// aggregating `m` range proofs of `n` bits each.
5686#[ derive( Clone ) ]
5787pub struct Generators {
58- /// Number of bits in a rangeproof
59- pub n : usize ,
60- /// Number of values or parties
61- pub m : usize ,
6288 /// Bases for Pedersen commitments
6389 pub pedersen_gens : PedersenGenerators ,
90+ /// The maximum number of usable generators for each party.
91+ capacity : usize ,
92+ /// Number of values or parties
93+ parties : usize ,
6494 /// Per-bit generators for the bit values
65- pub G : Vec < RistrettoPoint > ,
66- /// Per-bit generators for the bit blinding factors
67- pub H : Vec < RistrettoPoint > ,
68- }
69-
70- /// The `GeneratorsView` is produced by `Generators::share()`.
71- ///
72- /// The `Generators` struct represents generators for an aggregated
73- /// range proof `m` proofs of `n` bits each; the `GeneratorsView`
74- /// represents the generators for one of the `m` parties' shares.
75- #[ derive( Copy , Clone ) ]
76- pub struct GeneratorsView < ' a > {
77- /// Bases for Pedersen commitments
78- pub pedersen_gens : & ' a PedersenGenerators ,
79- /// Per-bit generators for the bit values
80- pub G : & ' a [ RistrettoPoint ] ,
95+ G_vec : Vec < Vec < RistrettoPoint > > ,
8196 /// Per-bit generators for the bit blinding factors
82- pub H : & ' a [ RistrettoPoint ] ,
83- }
84-
85- /// Represents a pair of base points for Pedersen commitments.
86- #[ derive( Copy , Clone ) ]
87- pub struct PedersenGenerators {
88- /// Base for the committed value
89- pub B : RistrettoPoint ,
90-
91- /// Base for the blinding factor
92- pub B_blinding : RistrettoPoint ,
93- }
94-
95- impl PedersenGenerators {
96- /// Creates a Pedersen commitment using the value scalar and a blinding factor.
97- pub fn commit ( & self , value : Scalar , blinding : Scalar ) -> RistrettoPoint {
98- RistrettoPoint :: multiscalar_mul ( & [ value, blinding] , & [ self . B , self . B_blinding ] )
99- }
100- }
101-
102- impl Default for PedersenGenerators {
103- fn default ( ) -> Self {
104- PedersenGenerators {
105- B : GeneratorsChain :: new ( b"Bulletproofs.Generators.B" )
106- . next ( )
107- . unwrap ( ) ,
108- B_blinding : GeneratorsChain :: new ( b"Bulletproofs.Generators.B_blinding" )
109- . next ( )
110- . unwrap ( ) ,
111- }
112- }
97+ H_vec : Vec < Vec < RistrettoPoint > > ,
11398}
11499
115100impl Generators {
116- /// Creates generators for `m` range proofs of `n` bits each .
117- pub fn new ( pedersen_gens : PedersenGenerators , n : usize , m : usize ) -> Self {
101+ /// Creates `capacity` generators for the given number of `parties` .
102+ pub fn new ( pedersen_gens : PedersenGenerators , capacity : usize , parties : usize ) -> Self {
118103 use byteorder:: { ByteOrder , LittleEndian } ;
119104
120- let G = ( 0 ..m )
121- . flat_map ( |i| {
105+ let G_vec = ( 0 ..parties )
106+ . map ( |i| {
122107 let party_index = i as u32 ;
123108 let mut label = [ b'G' , 0 , 0 , 0 , 0 ] ;
124109 LittleEndian :: write_u32 ( & mut label[ 1 ..5 ] , party_index) ;
125110
126- GeneratorsChain :: new ( & label) . take ( n)
111+ GeneratorsChain :: new ( & label)
112+ . take ( capacity)
113+ . collect :: < Vec < _ > > ( )
127114 } )
128115 . collect ( ) ;
129116
130- let H = ( 0 ..m )
131- . flat_map ( |i| {
117+ let H_vec = ( 0 ..parties )
118+ . map ( |i| {
132119 let party_index = i as u32 ;
133120 let mut label = [ b'H' , 0 , 0 , 0 , 0 ] ;
134121 LittleEndian :: write_u32 ( & mut label[ 1 ..5 ] , party_index) ;
135122
136- GeneratorsChain :: new ( & label) . take ( n)
123+ GeneratorsChain :: new ( & label)
124+ . take ( capacity)
125+ . collect :: < Vec < _ > > ( )
137126 } )
138127 . collect ( ) ;
139128
140129 Generators {
141130 pedersen_gens,
142- n ,
143- m ,
144- G ,
145- H ,
131+ capacity ,
132+ parties ,
133+ G_vec ,
134+ H_vec ,
146135 }
147136 }
148137
149138 /// Returns j-th share of generators, with an appropriate
150139 /// slice of vectors G and H for the j-th range proof.
151140 pub fn share ( & self , j : usize ) -> GeneratorsView {
152- let lower = self . n * j;
153- let upper = self . n * ( j + 1 ) ;
154141 GeneratorsView {
155142 pedersen_gens : & self . pedersen_gens ,
156- G : & self . G [ lower..upper] ,
157- H : & self . H [ lower..upper] ,
143+ gens : & self ,
144+ share : j,
145+ }
146+ }
147+
148+ /// Get the maximum number of generators that can be used in a proof.
149+ pub fn capacity ( & self ) -> usize {
150+ self . capacity
151+ }
152+
153+ /// Return an iterator over the aggregation of the parties' G generators with given size `n`.
154+ pub ( crate ) fn G ( & self , n : usize ) -> impl Iterator < Item = & RistrettoPoint > {
155+ AggregatedGensIter {
156+ n,
157+ array : & self . G_vec ,
158+ party_idx : 0 ,
159+ gen_idx : 0 ,
160+ }
161+ }
162+
163+ /// Return an iterator over the aggregation of the parties' H generators with given size `n`.
164+ pub ( crate ) fn H ( & self , n : usize ) -> impl Iterator < Item = & RistrettoPoint > {
165+ AggregatedGensIter {
166+ n,
167+ array : & self . H_vec ,
168+ party_idx : 0 ,
169+ gen_idx : 0 ,
170+ }
171+ }
172+ }
173+
174+ struct AggregatedGensIter < ' a > {
175+ array : & ' a Vec < Vec < RistrettoPoint > > ,
176+ n : usize ,
177+ party_idx : usize ,
178+ gen_idx : usize ,
179+ }
180+
181+ impl < ' a > Iterator for AggregatedGensIter < ' a > {
182+ type Item = & ' a RistrettoPoint ;
183+
184+ fn next ( & mut self ) -> Option < Self :: Item > {
185+ if self . gen_idx >= self . n {
186+ self . gen_idx = 0 ;
187+ self . party_idx += 1 ;
158188 }
189+
190+ if self . party_idx >= self . array . len ( ) {
191+ None
192+ } else {
193+ let cur_gen = self . gen_idx ;
194+ self . gen_idx += 1 ;
195+ Some ( & self . array [ self . party_idx ] [ cur_gen] )
196+ }
197+ }
198+
199+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
200+ let size = self . n * self . array . len ( ) ;
201+ ( size, Some ( size) )
202+ }
203+ }
204+
205+ /// The `GeneratorsView` is produced by `Generators::share()`.
206+ ///
207+ /// The `Generators` struct represents generators for an aggregated
208+ /// range proof `m` proofs of `n` bits each; the `GeneratorsView`
209+ /// represents the generators for one of the `m` parties' shares.
210+ #[ derive( Copy , Clone ) ]
211+ pub struct GeneratorsView < ' a > {
212+ /// Bases for Pedersen commitments
213+ pub pedersen_gens : & ' a PedersenGenerators ,
214+ /// The parent object that this is a view into
215+ gens : & ' a Generators ,
216+ /// Which share we are
217+ share : usize ,
218+ }
219+
220+ impl < ' a > GeneratorsView < ' a > {
221+ /// Return an iterator over this party's G generators with given size `n`.
222+ pub ( crate ) fn G ( & self , n : usize ) -> impl Iterator < Item = & ' a RistrettoPoint > {
223+ self . gens . G_vec [ self . share ] . iter ( ) . take ( n)
224+ }
225+
226+ /// Return an iterator over this party's H generators with given size `n`.
227+ pub ( crate ) fn H ( & self , n : usize ) -> impl Iterator < Item = & ' a RistrettoPoint > {
228+ self . gens . H_vec [ self . share ] . iter ( ) . take ( n)
159229 }
160230}
161231
@@ -164,24 +234,36 @@ mod tests {
164234 extern crate hex;
165235 use super :: * ;
166236
237+ // XXX write tests
238+
167239 #[ test]
168- fn rangeproof_generators ( ) {
169- let n = 2 ;
170- let m = 3 ;
171- let gens = Generators :: new ( PedersenGenerators :: default ( ) , n, m) ;
172-
173- // The concatenation of shares must be the full generator set
174- assert_eq ! (
175- [ gens. G [ ..n] . to_vec( ) , gens. H [ ..n] . to_vec( ) ] ,
176- [ gens. share( 0 ) . G [ ..] . to_vec( ) , gens. share( 0 ) . H [ ..] . to_vec( ) ]
177- ) ;
178- assert_eq ! (
179- [ gens. G [ n..] [ ..n] . to_vec( ) , gens. H [ n..] [ ..n] . to_vec( ) ] ,
180- [ gens. share( 1 ) . G [ ..] . to_vec( ) , gens. share( 1 ) . H [ ..] . to_vec( ) ]
181- ) ;
182- assert_eq ! (
183- [ gens. G [ 2 * n..] [ ..n] . to_vec( ) , gens. H [ 2 * n..] [ ..n] . to_vec( ) ] ,
184- [ gens. share( 2 ) . G [ ..] . to_vec( ) , gens. share( 2 ) . H [ ..] . to_vec( ) ]
185- ) ;
240+ fn aggregated_gens_iter_matches_flat_map ( ) {
241+ let gens = Generators :: new ( PedersenGenerators :: default ( ) , 64 , 8 ) ;
242+
243+ let helper = |n : usize | {
244+ let agg_G: Vec < RistrettoPoint > = gens. G ( n) . cloned ( ) . collect ( ) ;
245+ let flat_G: Vec < RistrettoPoint > = gens
246+ . G_vec
247+ . iter ( )
248+ . flat_map ( move |G_j | G_j . iter ( ) . take ( n) )
249+ . cloned ( )
250+ . collect ( ) ;
251+
252+ let agg_H: Vec < RistrettoPoint > = gens. H ( n) . cloned ( ) . collect ( ) ;
253+ let flat_H: Vec < RistrettoPoint > = gens
254+ . H_vec
255+ . iter ( )
256+ . flat_map ( move |H_j | H_j . iter ( ) . take ( n) )
257+ . cloned ( )
258+ . collect ( ) ;
259+
260+ assert_eq ! ( agg_G, flat_G) ;
261+ assert_eq ! ( agg_H, flat_H) ;
262+ } ;
263+
264+ helper ( 64 ) ;
265+ helper ( 32 ) ;
266+ helper ( 16 ) ;
267+ helper ( 8 ) ;
186268 }
187269}
0 commit comments