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