diff --git a/include/secp256k1_silentpayments.h b/include/secp256k1_silentpayments.h index 3a4c57907a..3adc1d575b 100644 --- a/include/secp256k1_silentpayments.h +++ b/include/secp256k1_silentpayments.h @@ -169,6 +169,29 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_l unsigned int m ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Create Silent Payment labelled spend public key. + * + * Given a recipient's spend public key B_spend and a label_tweak, calculate + * the corresponding serialized labelled spend public key: + * + * B_m = B_spend + label_tweak * G + * + * The result is used by the receiver to create a Silent Payment address, consisting + * of the serialized and concatenated scan public key and (labelled) spend public key each. + * + * Returns: 1 if labelled spend public key creation was successful. 0 if an error occured. + * Args: ctx: pointer to a context object + * Out: l_addr_spend_pubkey33: pointer to the resulting labelled spend public key + * In: receiver_spend_pubkey: pointer to the receiver's scan pubkey + * label_tweak: pointer to the the receiver's spend + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_address_spend_pubkey( + const secp256k1_context *ctx, + unsigned char *l_addr_spend_pubkey33, + const secp256k1_pubkey *receiver_spend_pubkey, + const unsigned char *label_tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + #ifdef __cplusplus } #endif diff --git a/src/modules/silentpayments/main_impl.h b/src/modules/silentpayments/main_impl.h index 880268a5b8..018d13bc2c 100644 --- a/src/modules/silentpayments/main_impl.h +++ b/src/modules/silentpayments/main_impl.h @@ -238,4 +238,29 @@ int secp256k1_silentpayments_create_label_tweak(const secp256k1_context *ctx, un return 1; } +int secp256k1_silentpayments_create_address_spend_pubkey(const secp256k1_context *ctx, unsigned char *l_addr_spend_pubkey33, const secp256k1_pubkey *receiver_spend_pubkey, const unsigned char *label_tweak32) { + secp256k1_ge B_m; + size_t ser_size; + int ser_ret; + + /* Sanity check inputs. */ + VERIFY_CHECK(ctx != NULL); + VERIFY_CHECK(l_addr_spend_pubkey33 != NULL); + VERIFY_CHECK(receiver_spend_pubkey != NULL); + VERIFY_CHECK(label_tweak32 != NULL); + + /* Calculate B_m = B_spend + label_tweak * G */ + secp256k1_pubkey_load(ctx, &B_m, receiver_spend_pubkey); + if (!secp256k1_ec_pubkey_tweak_add_helper(&B_m, label_tweak32)) { + return 0; + } + + /* Serialize B_m */ + ser_ret = secp256k1_eckey_pubkey_serialize(&B_m, l_addr_spend_pubkey33, &ser_size, 1); + VERIFY_CHECK(ser_ret && ser_size == 33); + (void)ser_ret; + + return 1; +} + #endif