@@ -359,7 +359,7 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
359
359
/* Now we just have a Schnorr signature in (e, s) form. The verification
360
360
* equation is e == H(sG - eX || proof params) */
361
361
362
- /* 1 . Compute slow/overwrought commitment to proof params */
362
+ /* 0 . Compute slow/overwrought commitment to proof params */
363
363
secp256k1_sha256_initialize (& sha2 );
364
364
secp256k1_rangeproof_serialize_point (tmpch , & commitp );
365
365
secp256k1_sha256_write (& sha2 , tmpch , 33 );
@@ -375,7 +375,7 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
375
375
return 0 ;
376
376
}
377
377
378
- /* 1. Compute R = sG - eX */
378
+ /* 1. Compute R = sG + eX */
379
379
secp256k1_scalar_set_b32 (& ss , & proof [offset + 32 ], & overflow );
380
380
if (overflow || secp256k1_scalar_is_zero (& ss )) {
381
381
return 0 ;
@@ -397,4 +397,115 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
397
397
return !secp256k1_memcmp_var (tmpch , & proof [offset ], 32 );
398
398
}
399
399
400
+ int secp256k1_rangeproof_create_value (const secp256k1_context * ctx , unsigned char * proof , size_t * plen , uint64_t value , const unsigned char * blind , const secp256k1_pedersen_commitment * commit , const secp256k1_generator * gen ) {
401
+ secp256k1_ge commitp ;
402
+ secp256k1_ge genp ;
403
+ secp256k1_gej tmpj ;
404
+ secp256k1_ge tmpp ;
405
+ secp256k1_scalar es ;
406
+ secp256k1_scalar ks ;
407
+ secp256k1_scalar xs ;
408
+ secp256k1_sha256 sha2 ;
409
+ unsigned char tmpch [33 ];
410
+ unsigned char pp_comm [32 ];
411
+ size_t offset ;
412
+ size_t sz ;
413
+ int overflow ;
414
+
415
+ VERIFY_CHECK (ctx != NULL );
416
+ ARG_CHECK (secp256k1_ecmult_gen_context_is_built (& ctx -> ecmult_gen_ctx ));
417
+ ARG_CHECK (proof != NULL );
418
+ ARG_CHECK (plen != NULL );
419
+ ARG_CHECK (blind != NULL );
420
+ ARG_CHECK (commit != NULL );
421
+ ARG_CHECK (gen != NULL );
422
+
423
+ if (* plen < (value == 0 ? 65 : 73 )) {
424
+ return 0 ;
425
+ }
426
+ * plen = value == 0 ? 65 : 73 ;
427
+
428
+ secp256k1_pedersen_commitment_load (& commitp , commit );
429
+ secp256k1_generator_load (& genp , gen );
430
+
431
+ /* Encode header */
432
+ if (value > 0 ) {
433
+ proof [0 ] = 0x20 ;
434
+ proof [1 ] = value >> 56 ;
435
+ proof [2 ] = value >> 48 ;
436
+ proof [3 ] = value >> 40 ;
437
+ proof [4 ] = value >> 32 ;
438
+ proof [5 ] = value >> 24 ;
439
+ proof [6 ] = value >> 16 ;
440
+ proof [7 ] = value >> 8 ;
441
+ proof [8 ] = value ;
442
+ offset = 9 ;
443
+ } else {
444
+ proof [0 ] = 0x00 ;
445
+ offset = 1 ;
446
+ }
447
+
448
+ /* Now we have to make a Schnorr signature in (e, s) form. */
449
+
450
+ /* 1. Compute random k */
451
+ secp256k1_sha256_initialize (& sha2 );
452
+ secp256k1_sha256_write (& sha2 , blind , 32 );
453
+ secp256k1_sha256_write (& sha2 , proof , offset );
454
+ secp256k1_rangeproof_serialize_point (tmpch , & genp );
455
+ secp256k1_sha256_write (& sha2 , tmpch , 33 );
456
+ secp256k1_sha256_finalize (& sha2 , tmpch );
457
+ secp256k1_scalar_set_b32 (& ks , tmpch , & overflow );
458
+ if (overflow || secp256k1_scalar_is_zero (& ks )) {
459
+ secp256k1_scalar_clear (& ks );
460
+ memset (tmpch , 0 , sizeof (tmpch ));
461
+ return 0 ;
462
+ }
463
+
464
+ /* 2. Compute R = kG */
465
+ secp256k1_ecmult_gen (& ctx -> ecmult_gen_ctx , & tmpj , & ks );
466
+ secp256k1_ge_set_gej (& tmpp , & tmpj );
467
+
468
+ /* 3. Compute slow/overwrought commitment to proof params */
469
+ secp256k1_sha256_initialize (& sha2 );
470
+ secp256k1_rangeproof_serialize_point (tmpch , & commitp );
471
+ secp256k1_sha256_write (& sha2 , tmpch , 33 );
472
+ secp256k1_rangeproof_serialize_point (tmpch , & genp );
473
+ secp256k1_sha256_write (& sha2 , tmpch , 33 );
474
+ secp256k1_sha256_write (& sha2 , proof , offset );
475
+ secp256k1_sha256_finalize (& sha2 , pp_comm );
476
+
477
+ /* 4. Compute e0 = H(R || proof params) and serialize it into the proof */
478
+ secp256k1_sha256_initialize (& sha2 );
479
+ secp256k1_eckey_pubkey_serialize (& tmpp , tmpch , & sz , 1 );
480
+ secp256k1_sha256_write (& sha2 , tmpch , sz );
481
+ secp256k1_sha256_write (& sha2 , pp_comm , sizeof (pp_comm ));
482
+ secp256k1_sha256_finalize (& sha2 , & proof [offset ]);
483
+
484
+ /* ... feed this into our hash e, along with e0 */
485
+ secp256k1_borromean_hash (tmpch , pp_comm , 32 , & proof [offset ], 32 , 0 , 0 );
486
+ secp256k1_scalar_set_b32 (& es , tmpch , & overflow );
487
+ if (overflow || secp256k1_scalar_is_zero (& es )) {
488
+ secp256k1_scalar_clear (& ks );
489
+ secp256k1_scalar_clear (& es );
490
+ return 0 ;
491
+ }
492
+
493
+ /* 5. Compute k - ex from this, and serialize it */
494
+ secp256k1_scalar_set_b32 (& xs , blind , & overflow );
495
+ if (overflow || secp256k1_scalar_is_zero (& xs )) {
496
+ secp256k1_scalar_clear (& ks );
497
+ secp256k1_scalar_clear (& xs );
498
+ secp256k1_scalar_clear (& es );
499
+ return 0 ;
500
+ }
501
+ secp256k1_scalar_mul (& es , & es , & xs );
502
+ secp256k1_scalar_negate (& es , & es );
503
+ secp256k1_scalar_add (& es , & es , & ks );
504
+ secp256k1_scalar_get_b32 (& proof [offset + 32 ], & es );
505
+
506
+ secp256k1_scalar_clear (& ks );
507
+ secp256k1_scalar_clear (& xs );
508
+ return 1 ;
509
+ }
510
+
400
511
#endif
0 commit comments