@@ -121,6 +121,105 @@ static int secp256k1_rangeproof_header_parse(
121121 return secp256k1_rangeproof_header_expand (header );
122122}
123123
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+
124223SECP256K1_INLINE static void secp256k1_rangeproof_pub_expand (secp256k1_gej * pubs ,
125224 int exp , size_t * rsizes , size_t rings , const secp256k1_ge * genp ) {
126225 secp256k1_gej base ;
@@ -214,88 +313,12 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec,
214313 return ret ;
215314}
216315
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-
294316/* 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. */
295317SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl (const secp256k1_ecmult_gen_context * ecmult_gen_ctx ,
296318 unsigned char * proof , size_t * plen , uint64_t min_value ,
297319 const secp256k1_ge * commit , const unsigned char * blind , const unsigned char * nonce , int exp , int min_bits , uint64_t value ,
298320 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 ;
299322 secp256k1_gej pubs [128 ]; /* Candidate digits for our proof, most inferred. */
300323 secp256k1_scalar s [128 ]; /* Signatures in our proof, most forged. */
301324 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
305328 unsigned char tmp [33 ];
306329 unsigned char * signs ; /* Location of sign flags in the proof. */
307330 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. */
312331 secp256k1_borromean_sz_closure secidx_closure ;
313332 size_t len ; /* Number of bytes used so far. */
314333 size_t i ;
334+ size_t pub_idx ;
315335 int overflow ;
316- size_t npub ;
317336 len = 0 ;
318- if (* plen < 65 || min_value > value || min_bits > 64 || min_bits < 0 || exp < -1 || exp > 18 ) {
337+ if (* plen < 65 ) {
319338 return 0 ;
320339 }
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 )) {
322342 return 0 ;
323343 }
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 );
336348 }
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+
337357 /* Do we have enough room in the proof for the message? Each ring gives us 128 bytes, but the
338358 * final ring is used to encode the blinding factor and the value, so we can't use that. (Well,
339359 * technically there are 64 bytes available if we avoided the other data, but this is difficult
340360 * 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 )) {
342362 return 0 ;
343363 }
344364 /* 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 )) {
346366 return 0 ;
347367 }
348368 secp256k1_sha256_initialize (& sha256_m );
@@ -357,19 +377,19 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
357377 memcpy (prep , message , msg_len );
358378 }
359379 /* 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 ) {
361381 size_t idx ;
362382 /* 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 ;
366386 for (i = 0 ; i < 8 ; i ++ ) {
367387 prep [8 + i + idx ] = prep [16 + i + idx ] = prep [24 + i + idx ] = (v >> (56 - i * 8 )) & 255 ;
368388 prep [i + idx ] = 0 ;
369389 }
370390 prep [idx ] = 128 ;
371391 }
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 )) {
373393 return 0 ;
374394 }
375395 memset (prep , 0 , 4096 );
@@ -380,51 +400,51 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
380400 * blinded value for one digit.
381401 */
382402 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 ])) {
385405 return 0 ;
386406 }
387407 signs = & proof [len ];
388408 /* 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 ++ ) {
390410 signs [i ] = 0 ;
391411 len ++ ;
392412 }
393- npub = 0 ;
394- for (i = 0 ; i < rings ; i ++ ) {
413+ pub_idx = 0 ;
414+ for (i = 0 ; i < header . n_rings ; i ++ ) {
395415 uint64_t secidx_i = secidx_closure .call (& secidx_closure , i );
396416 /*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 ])) {
399419 return 0 ;
400420 }
401- if (i < rings - 1 ) {
421+ if (i < header . n_rings - 1 ) {
402422 unsigned char tmpc [33 ];
403423 secp256k1_ge c ;
404424 unsigned char quadness ;
405425 /*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 ]);
408428 secp256k1_rangeproof_serialize_point (tmpc , & c );
409429 quadness = tmpc [0 ];
410430 secp256k1_sha256_write (& sha256_m , tmpc , 33 );
411431 signs [i >>3 ] |= quadness << (i & 7 );
412432 memcpy (& proof [len ], tmpc + 1 , 32 );
413433 len += 32 ;
414434 }
415- npub += rsizes [i ];
435+ pub_idx += header . rsizes [i ];
416436 }
417- secp256k1_rangeproof_pub_expand (pubs , exp , rsizes , rings , genp );
437+ secp256k1_rangeproof_pub_expand (pubs , header . exp , header . rsizes , header . n_rings , genp );
418438 if (extra_commit != NULL ) {
419439 secp256k1_sha256_write (& sha256_m , extra_commit , extra_commit_len );
420440 }
421441 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 )) {
423443 return 0 ;
424444 }
425445 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 ]);
428448 len += 32 ;
429449 }
430450 VERIFY_CHECK (len <= * plen );
0 commit comments