@@ -121,6 +121,105 @@ static int secp256k1_rangeproof_header_parse(
121
121
return secp256k1_rangeproof_header_expand (header );
122
122
}
123
123
124
+ static int secp256k1_rangeproof_header_set_for_value (
125
+ secp256k1_rangeproof_header * header ,
126
+ uint64_t * proven_value ,
127
+ const uint64_t min_value ,
128
+ const uint64_t min_bits ,
129
+ const int exp ,
130
+ const uint64_t value
131
+ ) {
132
+ memset (header , 0 , sizeof (* header ));
133
+ * proven_value = 0 ;
134
+
135
+ /* Sanity checks */
136
+ if (min_value > value || min_bits > 64 || exp < -1 || exp > 18 ) {
137
+ return 0 ;
138
+ }
139
+
140
+ /* Start by just using the user's requested values, then adjust them in
141
+ * various ways to make them compatible. This is probably not advisable
142
+ * from a privacy point-of-view but it's important to be compatible with
143
+ * the 2015-era API, and all of these issues will go away when we merge
144
+ * Bulletproofs. */
145
+ header -> exp = exp ;
146
+ header -> min_value = min_value ;
147
+ header -> mantissa = min_bits ? min_bits : 1 ; /* force mantissa to be nonzero */
148
+
149
+ /* Special-case single-value proofs */
150
+ if (header -> exp == -1 ) {
151
+ header -> mantissa = 0 ; /* ignore user's min_bits */
152
+ return secp256k1_rangeproof_header_expand (header );
153
+ }
154
+
155
+ /* Deal with extreme values (copied directly from 2015 code) */
156
+ if (min_bits > 61 || value > INT64_MAX ) {
157
+ /* Ten is not a power of two, so dividing by ten and then representing in base-2 times ten
158
+ * expands the representable range. The verifier requires the proven range is within 0..2**64.
159
+ * For very large numbers (all over 2**63) we must change our exponent to compensate.
160
+ * Rather than handling it precisely, this just disables use of the exponent for big values.
161
+ */
162
+ header -> exp = 0 ;
163
+ }
164
+ {
165
+ /* If the user has asked for more bits of proof then there is room for in the exponent, reduce the exponent. */
166
+ uint64_t max = min_bits ? (UINT64_MAX >> (64 - min_bits )) : 0 ;
167
+ int i ;
168
+ for (i = 0 ; i < header -> exp && max <= UINT64_MAX / 10 ; i ++ ) {
169
+ max *= 10 ;
170
+ }
171
+ header -> exp = i ;
172
+ }
173
+
174
+
175
+ /* Increase the mantissa from min_bits until it actually covers the proven value */
176
+ if (!secp256k1_rangeproof_header_expand (header )) {
177
+ return 0 ;
178
+ }
179
+ * proven_value = (value - header -> min_value ) / header -> scale ;
180
+ while (header -> mantissa < 64 && (* proven_value >> header -> mantissa ) > 0 ) {
181
+ header -> mantissa ++ ;
182
+ }
183
+ /* Fudge min_value so we don't lose the low-order digits of `value` */
184
+ header -> min_value = value - (* proven_value * header -> scale );
185
+
186
+ /* Increasing the mantissa will have increased the number of rings etc
187
+ * so re-expand the header to recompute the other derived values. */
188
+ return secp256k1_rangeproof_header_expand (header );
189
+ }
190
+
191
+ static int secp256k1_rangeproof_header_serialize (
192
+ unsigned char * proof ,
193
+ size_t plen ,
194
+ size_t * offset ,
195
+ const secp256k1_rangeproof_header * header
196
+ ) {
197
+ * offset = 0 ;
198
+ if (plen < 65 ) {
199
+ return 0 ;
200
+ }
201
+
202
+ /* Write control byte */
203
+ proof [0 ] = (header -> exp >= 0 ? (64 | header -> exp ) : 0 ) | (header -> min_value ? 32 : 0 );
204
+ * offset += 1 ;
205
+ /* Write mantissa, for non-exact-value proofs */
206
+ if (header -> exp >= 0 ) {
207
+ VERIFY_CHECK (header -> mantissa > 0 && header -> mantissa <= 64 );
208
+ proof [1 ] = header -> mantissa - 1 ;
209
+ * offset += 1 ;
210
+ }
211
+ /* Write min_value, if present */
212
+ if (header -> min_value > 0 ) {
213
+ size_t i ;
214
+ for (i = 0 ; i < 8 ; i ++ ) {
215
+ proof [* offset + i ] = (header -> min_value >> ((7 - i ) * 8 )) & 255 ;
216
+ }
217
+ * offset += 8 ;
218
+ }
219
+
220
+ return 1 ;
221
+ }
222
+
124
223
SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand (secp256k1_gej * pubs ,
125
224
int exp , size_t * rsizes , size_t rings , const secp256k1_ge * genp ) {
126
225
secp256k1_gej base ;
@@ -214,88 +313,12 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec,
214
313
return ret ;
215
314
}
216
315
217
- SECP256K1_INLINE static int secp256k1_range_proveparams (uint64_t * v , size_t * rings , size_t * rsizes , size_t * npub , secp256k1_borromean_sz_closure * secidx_closure , uint64_t * min_value ,
218
- int * mantissa , uint64_t * scale , int * exp , int * min_bits , uint64_t value ) {
219
- size_t i ;
220
- * rings = 1 ;
221
- rsizes [0 ] = 1 ;
222
- * scale = 1 ;
223
- * mantissa = 0 ;
224
- * npub = 0 ;
225
- if (* min_value == UINT64_MAX ) {
226
- /* If the minimum value is the maximal representable value, then we cannot code a range. */
227
- * exp = -1 ;
228
- }
229
- if (* exp >= 0 ) {
230
- int max_bits ;
231
- uint64_t v2 ;
232
- if ((* min_value && value > INT64_MAX ) || (value && * min_value >= INT64_MAX )) {
233
- /* If either value or min_value is >= 2^63-1 then the other must by zero to avoid overflowing the proven range. */
234
- return 0 ;
235
- }
236
- max_bits = * min_value ? secp256k1_clz64_var (* min_value ) : 64 ;
237
- if (* min_bits > max_bits ) {
238
- * min_bits = max_bits ;
239
- }
240
- if (* min_bits > 61 || value > INT64_MAX ) {
241
- /** Ten is not a power of two, so dividing by ten and then representing in base-2 times ten
242
- * expands the representable range. The verifier requires the proven range is within 0..2**64.
243
- * For very large numbers (all over 2**63) we must change our exponent to compensate.
244
- * Rather than handling it precisely, this just disables use of the exponent for big values.
245
- */
246
- * exp = 0 ;
247
- }
248
- /* Mask off the least significant digits, as requested. */
249
- * v = value - * min_value ;
250
- /* If the user has asked for more bits of proof then there is room for in the exponent, reduce the exponent. */
251
- v2 = * min_bits ? (UINT64_MAX >>(64 - * min_bits )) : 0 ;
252
- for (i = 0 ; (int ) i < * exp && (v2 <= UINT64_MAX / 10 ); i ++ ) {
253
- * v /= 10 ;
254
- v2 *= 10 ;
255
- }
256
- * exp = i ;
257
- v2 = * v ;
258
- for (i = 0 ; (int ) i < * exp ; i ++ ) {
259
- v2 *= 10 ;
260
- * scale *= 10 ;
261
- }
262
- /* If the masked number isn't precise, compute the public offset. */
263
- * min_value = value - v2 ;
264
- /* How many bits do we need to represent our value? */
265
- * mantissa = * v ? 64 - secp256k1_clz64_var (* v ) : 1 ;
266
- if (* min_bits > * mantissa ) {
267
- /* If the user asked for more precision, give it to them. */
268
- * mantissa = * min_bits ;
269
- }
270
- /* Digits in radix-4, except for the last digit if our mantissa length is odd. */
271
- * rings = (* mantissa + 1 ) >> 1 ;
272
- for (i = 0 ; i < * rings ; i ++ ) {
273
- rsizes [i ] = ((i < * rings - 1 ) | (!(* mantissa & 1 ))) ? 4 : 2 ;
274
- * npub += rsizes [i ];
275
- }
276
- VERIFY_CHECK (* mantissa > 0 );
277
- VERIFY_CHECK ((* v & ~(UINT64_MAX >>(64 - * mantissa ))) == 0 ); /* Did this get all the bits? */
278
- * secidx_closure = secp256k1_borromean_sz_closure_secidx (* v );
279
- } else {
280
- /* A proof for an exact value. */
281
- * exp = 0 ;
282
- * min_value = value ;
283
- * v = 0 ;
284
- * npub = 2 ;
285
- * secidx_closure = secp256k1_borromean_sz_closure_const (0 );
286
- }
287
- VERIFY_CHECK (* v * * scale + * min_value == value );
288
- VERIFY_CHECK (* rings > 0 );
289
- VERIFY_CHECK (* rings <= 32 );
290
- VERIFY_CHECK (* npub <= 128 );
291
- return 1 ;
292
- }
293
-
294
316
/* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */
295
317
SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl (const secp256k1_ecmult_gen_context * ecmult_gen_ctx ,
296
318
unsigned char * proof , size_t * plen , uint64_t min_value ,
297
319
const secp256k1_ge * commit , const unsigned char * blind , const unsigned char * nonce , int exp , int min_bits , uint64_t value ,
298
320
const unsigned char * message , size_t msg_len , const unsigned char * extra_commit , size_t extra_commit_len , const secp256k1_ge * genp ){
321
+ secp256k1_rangeproof_header header ;
299
322
secp256k1_gej pubs [128 ]; /* Candidate digits for our proof, most inferred. */
300
323
secp256k1_scalar s [128 ]; /* Signatures in our proof, most forged. */
301
324
secp256k1_scalar sec [32 ]; /* Blinding factors for the correct digits. */
@@ -305,44 +328,41 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
305
328
unsigned char tmp [33 ];
306
329
unsigned char * signs ; /* Location of sign flags in the proof. */
307
330
uint64_t v ;
308
- uint64_t scale ; /* scale = 10^exp. */
309
- int mantissa ; /* Number of bits proven in the blinded value. */
310
- size_t rings ; /* How many digits will our proof cover. */
311
- size_t rsizes [32 ]; /* How many possible values there are for each place. */
312
331
secp256k1_borromean_sz_closure secidx_closure ;
313
332
size_t len ; /* Number of bytes used so far. */
314
333
size_t i ;
334
+ size_t pub_idx ;
315
335
int overflow ;
316
- size_t npub ;
317
336
len = 0 ;
318
- if (* plen < 65 || min_value > value || min_bits > 64 || min_bits < 0 || exp < -1 || exp > 18 ) {
337
+ if (* plen < 65 ) {
319
338
return 0 ;
320
339
}
321
- if (!secp256k1_range_proveparams (& v , & rings , rsizes , & npub , & secidx_closure , & min_value , & mantissa , & scale , & exp , & min_bits , value )) {
340
+
341
+ if (!secp256k1_rangeproof_header_set_for_value (& header , & v , min_value , min_bits , exp , value )) {
322
342
return 0 ;
323
343
}
324
- proof [len ] = (rsizes [0 ] > 1 ? (64 | exp ) : 0 ) | (min_value ? 32 : 0 );
325
- len ++ ;
326
- if (rsizes [0 ] > 1 ) {
327
- VERIFY_CHECK (mantissa > 0 && mantissa <= 64 );
328
- proof [len ] = mantissa - 1 ;
329
- len ++ ;
330
- }
331
- if (min_value ) {
332
- for (i = 0 ; i < 8 ; i ++ ) {
333
- proof [len + i ] = (min_value >> ((7 - i ) * 8 )) & 255 ;
334
- }
335
- len += 8 ;
344
+ if (header .exp >= 0 ) {
345
+ secidx_closure = secp256k1_borromean_sz_closure_secidx (v );
346
+ } else {
347
+ secidx_closure = secp256k1_borromean_sz_closure_const (0 );
336
348
}
349
+
350
+ VERIFY_CHECK (v * header .scale + header .min_value == value );
351
+ VERIFY_CHECK (header .n_rings > 0 );
352
+ VERIFY_CHECK (header .n_rings <= 32 );
353
+ VERIFY_CHECK (header .n_pubs <= 128 );
354
+
355
+ secp256k1_rangeproof_header_serialize (proof , * plen , & len , & header );
356
+
337
357
/* Do we have enough room in the proof for the message? Each ring gives us 128 bytes, but the
338
358
* final ring is used to encode the blinding factor and the value, so we can't use that. (Well,
339
359
* technically there are 64 bytes available if we avoided the other data, but this is difficult
340
360
* because it's not always in the same place. */
341
- if (msg_len > 0 && msg_len > 128 * (rings - 1 )) {
361
+ if (msg_len > 0 && msg_len > 128 * (header . n_rings - 1 )) {
342
362
return 0 ;
343
363
}
344
364
/* Do we have enough room for the proof? */
345
- if (* plen - len < 32 * (npub + rings - 1 ) + 32 + ((rings + 6 ) >> 3 )) {
365
+ if (* plen - len < 32 * (header . n_pubs + header . n_rings - 1 ) + 32 + ((header . n_rings + 6 ) >> 3 )) {
346
366
return 0 ;
347
367
}
348
368
secp256k1_sha256_initialize (& sha256_m );
@@ -357,19 +377,19 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
357
377
memcpy (prep , message , msg_len );
358
378
}
359
379
/* Note, the data corresponding to the blinding factors must be zero. */
360
- if (rsizes [rings - 1 ] > 1 ) {
380
+ if (header . rsizes [header . n_rings - 1 ] > 1 ) {
361
381
size_t idx ;
362
382
/* Value encoding sidechannel. */
363
- idx = rsizes [rings - 1 ] - 1 ;
364
- idx -= secidx_closure .call (& secidx_closure , rings - 1 ) == idx ;
365
- idx = ((rings - 1 ) * 4 + idx ) * 32 ;
383
+ idx = header . rsizes [header . n_rings - 1 ] - 1 ;
384
+ idx -= secidx_closure .call (& secidx_closure , header . n_rings - 1 ) == idx ;
385
+ idx = ((header . n_rings - 1 ) * 4 + idx ) * 32 ;
366
386
for (i = 0 ; i < 8 ; i ++ ) {
367
387
prep [8 + i + idx ] = prep [16 + i + idx ] = prep [24 + i + idx ] = (v >> (56 - i * 8 )) & 255 ;
368
388
prep [i + idx ] = 0 ;
369
389
}
370
390
prep [idx ] = 128 ;
371
391
}
372
- if (!secp256k1_rangeproof_genrand (sec , s , prep , rsizes , rings , nonce , commit , proof , len , genp )) {
392
+ if (!secp256k1_rangeproof_genrand (sec , s , prep , header . rsizes , header . n_rings , nonce , commit , proof , len , genp )) {
373
393
return 0 ;
374
394
}
375
395
memset (prep , 0 , 4096 );
@@ -380,51 +400,51 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
380
400
* blinded value for one digit.
381
401
*/
382
402
secp256k1_scalar_set_b32 (& stmp , blind , & overflow );
383
- secp256k1_scalar_add (& sec [rings - 1 ], & sec [rings - 1 ], & stmp );
384
- if (overflow || secp256k1_scalar_is_zero (& sec [rings - 1 ])) {
403
+ secp256k1_scalar_add (& sec [header . n_rings - 1 ], & sec [header . n_rings - 1 ], & stmp );
404
+ if (overflow || secp256k1_scalar_is_zero (& sec [header . n_rings - 1 ])) {
385
405
return 0 ;
386
406
}
387
407
signs = & proof [len ];
388
408
/* We need one sign bit for each blinded value we send. */
389
- for (i = 0 ; i < (rings + 6 ) >> 3 ; i ++ ) {
409
+ for (i = 0 ; i < (header . n_rings + 6 ) >> 3 ; i ++ ) {
390
410
signs [i ] = 0 ;
391
411
len ++ ;
392
412
}
393
- npub = 0 ;
394
- for (i = 0 ; i < rings ; i ++ ) {
413
+ pub_idx = 0 ;
414
+ for (i = 0 ; i < header . n_rings ; i ++ ) {
395
415
uint64_t secidx_i = secidx_closure .call (& secidx_closure , i );
396
416
/*OPT: Use the precomputed gen2 basis?*/
397
- secp256k1_pedersen_ecmult (ecmult_gen_ctx , & pubs [npub ], & sec [i ], (secidx_i * scale ) << (i * 2 ), genp );
398
- if (secp256k1_gej_is_infinity (& pubs [npub ])) {
417
+ secp256k1_pedersen_ecmult (ecmult_gen_ctx , & pubs [pub_idx ], & sec [i ], (secidx_i * header . scale ) << (i * 2 ), genp );
418
+ if (secp256k1_gej_is_infinity (& pubs [pub_idx ])) {
399
419
return 0 ;
400
420
}
401
- if (i < rings - 1 ) {
421
+ if (i < header . n_rings - 1 ) {
402
422
unsigned char tmpc [33 ];
403
423
secp256k1_ge c ;
404
424
unsigned char quadness ;
405
425
/*OPT: split loop and batch invert.*/
406
- /*OPT: do not compute full pubs[npub ] in ge form; we only need x */
407
- secp256k1_ge_set_gej_var (& c , & pubs [npub ]);
426
+ /*OPT: do not compute full pubs[pub_idx ] in ge form; we only need x */
427
+ secp256k1_ge_set_gej_var (& c , & pubs [pub_idx ]);
408
428
secp256k1_rangeproof_serialize_point (tmpc , & c );
409
429
quadness = tmpc [0 ];
410
430
secp256k1_sha256_write (& sha256_m , tmpc , 33 );
411
431
signs [i >>3 ] |= quadness << (i & 7 );
412
432
memcpy (& proof [len ], tmpc + 1 , 32 );
413
433
len += 32 ;
414
434
}
415
- npub += rsizes [i ];
435
+ pub_idx += header . rsizes [i ];
416
436
}
417
- secp256k1_rangeproof_pub_expand (pubs , exp , rsizes , rings , genp );
437
+ secp256k1_rangeproof_pub_expand (pubs , header . exp , header . rsizes , header . n_rings , genp );
418
438
if (extra_commit != NULL ) {
419
439
secp256k1_sha256_write (& sha256_m , extra_commit , extra_commit_len );
420
440
}
421
441
secp256k1_sha256_finalize (& sha256_m , tmp );
422
- if (!secp256k1_borromean_sign (ecmult_gen_ctx , & proof [len ], s , pubs , sec , rsizes , & secidx_closure , rings , tmp , 32 )) {
442
+ if (!secp256k1_borromean_sign (ecmult_gen_ctx , & proof [len ], s , pubs , sec , header . rsizes , & secidx_closure , header . n_rings , tmp , 32 )) {
423
443
return 0 ;
424
444
}
425
445
len += 32 ;
426
- for (i = 0 ; i < npub ; i ++ ) {
427
- secp256k1_scalar_get_b32 (& proof [len ],& s [i ]);
446
+ for (i = 0 ; i < pub_idx ; i ++ ) {
447
+ secp256k1_scalar_get_b32 (& proof [len ], & s [i ]);
428
448
len += 32 ;
429
449
}
430
450
VERIFY_CHECK (len <= * plen );
0 commit comments