@@ -359,7 +359,7 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
359359 /* Now we just have a Schnorr signature in (e, s) form. The verification
360360 * equation is e == H(sG - eX || proof params) */
361361
362- /* 1 . Compute slow/overwrought commitment to proof params */
362+ /* 0 . Compute slow/overwrought commitment to proof params */
363363 secp256k1_sha256_initialize (& sha2 );
364364 secp256k1_rangeproof_serialize_point (tmpch , & commitp );
365365 secp256k1_sha256_write (& sha2 , tmpch , 33 );
@@ -375,7 +375,7 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
375375 return 0 ;
376376 }
377377
378- /* 1. Compute R = sG - eX */
378+ /* 1. Compute R = sG + eX */
379379 secp256k1_scalar_set_b32 (& ss , & proof [offset + 32 ], & overflow );
380380 if (overflow || secp256k1_scalar_is_zero (& ss )) {
381381 return 0 ;
@@ -397,4 +397,105 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
397397 return !memcmp (tmpch , & proof [offset ], 32 );
398398}
399399
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+
400501#endif
0 commit comments