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