88#define SECP256K1_MODULE_RANGEPROOF_MAIN
99
1010#include "group.h"
11+ #include "print.h"
1112
1213#include "modules/rangeproof/pedersen_impl.h"
1314#include "modules/rangeproof/borromean_impl.h"
@@ -359,7 +360,7 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
359360 /* Now we just have a Schnorr signature in (e, s) form. The verification
360361 * equation is e == H(sG - eX || proof params) */
361362
362- /* 1 . Compute slow/overwrought commitment to proof params */
363+ /* 0 . Compute slow/overwrought commitment to proof params */
363364 secp256k1_sha256_initialize (& sha2 );
364365 secp256k1_rangeproof_serialize_point (tmpch , & commitp );
365366 secp256k1_sha256_write (& sha2 , tmpch , 33 );
@@ -375,7 +376,7 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
375376 return 0 ;
376377 }
377378
378- /* 1. Compute R = sG - eX */
379+ /* 1. Compute R = sG + eX */
379380 secp256k1_scalar_set_b32 (& ss , & proof [offset + 32 ], & overflow );
380381 if (overflow || secp256k1_scalar_is_zero (& ss )) {
381382 return 0 ;
@@ -397,4 +398,105 @@ int secp256k1_rangeproof_verify_value(const secp256k1_context* ctx, const unsign
397398 return !memcmp (tmpch , & proof [offset ], 32 );
398399}
399400
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+
400502#endif
0 commit comments