@@ -328,4 +328,109 @@ int secp256k1_silentpayments_recipient_create_labelled_spend_pubkey(const secp25
328
328
return 1 ;
329
329
}
330
330
331
+ int secp256k1_silentpayments_recipient_public_data_create (
332
+ const secp256k1_context * ctx ,
333
+ secp256k1_silentpayments_public_data * public_data ,
334
+ const unsigned char * outpoint_smallest36 ,
335
+ const secp256k1_xonly_pubkey * const * xonly_pubkeys ,
336
+ size_t n_xonly_pubkeys ,
337
+ const secp256k1_pubkey * const * plain_pubkeys ,
338
+ size_t n_plain_pubkeys
339
+ ) {
340
+ size_t i ;
341
+ size_t pubkeylen = 65 ;
342
+ secp256k1_pubkey A_sum ;
343
+ secp256k1_ge A_sum_ge , addend ;
344
+ secp256k1_gej A_sum_gej ;
345
+ unsigned char input_hash_local [32 ];
346
+
347
+ /* Sanity check inputs */
348
+ VERIFY_CHECK (ctx != NULL );
349
+ ARG_CHECK (public_data != NULL );
350
+ ARG_CHECK (plain_pubkeys == NULL || n_plain_pubkeys >= 1 );
351
+ ARG_CHECK (xonly_pubkeys == NULL || n_xonly_pubkeys >= 1 );
352
+ ARG_CHECK ((plain_pubkeys != NULL ) || (xonly_pubkeys != NULL ));
353
+ ARG_CHECK ((n_plain_pubkeys + n_xonly_pubkeys ) >= 1 );
354
+ ARG_CHECK (outpoint_smallest36 != NULL );
355
+ memset (input_hash_local , 0 , 32 );
356
+
357
+ /* Compute input public keys sum: A_sum = A_1 + A_2 + ... + A_n */
358
+ secp256k1_gej_set_infinity (& A_sum_gej );
359
+ for (i = 0 ; i < n_plain_pubkeys ; i ++ ) {
360
+ secp256k1_pubkey_load (ctx , & addend , plain_pubkeys [i ]);
361
+ secp256k1_gej_add_ge (& A_sum_gej , & A_sum_gej , & addend );
362
+ }
363
+ for (i = 0 ; i < n_xonly_pubkeys ; i ++ ) {
364
+ secp256k1_xonly_pubkey_load (ctx , & addend , xonly_pubkeys [i ]);
365
+ secp256k1_gej_add_ge (& A_sum_gej , & A_sum_gej , & addend );
366
+ }
367
+ if (secp256k1_gej_is_infinity (& A_sum_gej )) {
368
+ /* TODO: do we need a special error return code for this case? */
369
+ return 0 ;
370
+ }
371
+ secp256k1_ge_set_gej (& A_sum_ge , & A_sum_gej );
372
+
373
+ /* Compute input_hash = hash(outpoint_L || A_sum) */
374
+ secp256k1_silentpayments_calculate_input_hash (input_hash_local , outpoint_smallest36 , & A_sum_ge );
375
+ secp256k1_pubkey_save (& A_sum , & A_sum_ge );
376
+ /* serialize the public_data struct */
377
+ public_data -> data [0 ] = 0 ;
378
+ secp256k1_ec_pubkey_serialize (ctx , & public_data -> data [1 ], & pubkeylen , & A_sum , SECP256K1_EC_UNCOMPRESSED );
379
+ memcpy (& public_data -> data [1 + pubkeylen ], input_hash_local , 32 );
380
+ return 1 ;
381
+ }
382
+
383
+ int secp256k1_silentpayments_recipient_public_data_load (const secp256k1_context * ctx , secp256k1_pubkey * pubkey , unsigned char * input_hash , const secp256k1_silentpayments_public_data * public_data ) {
384
+ int combined ;
385
+ size_t pubkeylen = 65 ;
386
+ VERIFY_CHECK (ctx != NULL );
387
+ ARG_CHECK (pubkey != NULL );
388
+ ARG_CHECK (public_data != NULL );
389
+
390
+ combined = (int )public_data -> data [0 ];
391
+ ARG_CHECK (combined == 0 || combined == 1 );
392
+ if (combined ) {
393
+ ARG_CHECK (combined == 1 && input_hash == NULL );
394
+ } else {
395
+ ARG_CHECK (combined == 0 && input_hash != NULL );
396
+ memcpy (input_hash , & public_data -> data [1 + pubkeylen ], 32 );
397
+ }
398
+ if (!secp256k1_ec_pubkey_parse (ctx , pubkey , & public_data -> data [1 ], pubkeylen )) {
399
+ return 0 ;
400
+ }
401
+ return 1 ;
402
+ }
403
+
404
+ int secp256k1_silentpayments_recipient_public_data_serialize (const secp256k1_context * ctx , unsigned char * output33 , const secp256k1_silentpayments_public_data * public_data ) {
405
+ secp256k1_pubkey pubkey ;
406
+ unsigned char input_hash [32 ];
407
+ size_t pubkeylen = 33 ;
408
+
409
+ ARG_CHECK (public_data -> data [0 ] == 0 );
410
+ if (!secp256k1_silentpayments_recipient_public_data_load (ctx , & pubkey , input_hash , public_data )) {
411
+ return 0 ;
412
+ }
413
+ if (!secp256k1_ec_pubkey_tweak_mul (ctx , & pubkey , input_hash )) {
414
+ return 0 ;
415
+ }
416
+ secp256k1_ec_pubkey_serialize (ctx , output33 , & pubkeylen , & pubkey , SECP256K1_EC_COMPRESSED );
417
+ return 1 ;
418
+ }
419
+
420
+ int secp256k1_silentpayments_recipient_public_data_parse (const secp256k1_context * ctx , secp256k1_silentpayments_public_data * public_data , const unsigned char * input33 ) {
421
+ size_t inputlen = 33 ;
422
+ size_t pubkeylen = 65 ;
423
+ secp256k1_pubkey pubkey ;
424
+
425
+ ARG_CHECK (public_data != NULL );
426
+ ARG_CHECK (input33 != NULL );
427
+ if (!secp256k1_ec_pubkey_parse (ctx , & pubkey , input33 , inputlen )) {
428
+ return 0 ;
429
+ }
430
+ public_data -> data [0 ] = 1 ;
431
+ secp256k1_ec_pubkey_serialize (ctx , & public_data -> data [1 ], & pubkeylen , & pubkey , SECP256K1_EC_UNCOMPRESSED );
432
+ memset (& public_data -> data [1 + pubkeylen ], 0 , 32 );
433
+ return 1 ;
434
+ }
435
+
331
436
#endif
0 commit comments