Skip to content

Commit

Permalink
silentpayments: add public tweak data creation routine
Browse files Browse the repository at this point in the history
  • Loading branch information
theStack committed Jan 27, 2024
1 parent 74351a1 commit 2290e80
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
34 changes: 33 additions & 1 deletion include/secp256k1_silentpayments.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,39 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_send_cre
const secp256k1_pubkey *receiver_scan_pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/* TODO: add function API for receiver side. */
/** Create Silent Payment tweak data from input public keys.
*
* Given a list of n public keys A_1...A_n (one for each silent payment
* eligible input to spend) and a serialized outpoint_smallest, compute
* the corresponding input public keys tweak data:
*
* A_tweaked = (A_1 + A_2 + ... + A_n) * hash(outpoint_lowest || A)
*
* The public keys have to be passed in via two different parameter pairs,
* one for regular and one for x-only public keys, in order to avoid the need
* of users converting to a common pubkey format before calling this function.
* The resulting data is needed to create a shared secret for the receiver's side.
*
* Returns: 1 if tweak data creation was successful. 0 if an error occured.
* Args: ctx: pointer to a context object
* Out: public_tweak_data: pointer to the resulting public keys tweak data
* In: plain_pubkeys: pointer to an array of non-taproot public keys
* (can be NULL if no non-taproot inputs are used)
* n_plain_pubkeys: the number of non-taproot input public keys
* xonly_pubkeys: pointer to an array of taproot x-only public keys
* (can be NULL if no taproot input public keys are used)
* n_xonly_pubkeys: the number of taproot input public keys
* outpoint_smallest36: serialized smallest outpoint
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_public_tweak_data(
const secp256k1_context *ctx,
secp256k1_pubkey *public_tweak_data,
const secp256k1_pubkey *plain_pubkeys,
size_t n_plain_pubkeys,
const secp256k1_xonly_pubkey *xonly_pubkeys,
size_t n_xonly_pubkeys,
const unsigned char *outpoint_smallest36
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(7);

#ifdef __cplusplus
}
Expand Down
43 changes: 43 additions & 0 deletions src/modules/silentpayments/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,49 @@ int secp256k1_silentpayments_send_create_shared_secret(const secp256k1_context *
return 1;
}

int secp256k1_silentpayments_create_public_tweak_data(const secp256k1_context *ctx, secp256k1_pubkey *public_tweak_data, const secp256k1_pubkey *plain_pubkeys, size_t n_plain_pubkeys, const secp256k1_xonly_pubkey *xonly_pubkeys, size_t n_xonly_pubkeys, const unsigned char *outpoint_smallest36) {
size_t i;
secp256k1_ge A_sum_ge, addend;
secp256k1_gej A_sum_gej;
secp256k1_scalar input_hash_scalar;

/* Sanity check inputs */
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(public_tweak_data != NULL);
ARG_CHECK(plain_pubkeys == NULL || n_plain_pubkeys >= 1);
ARG_CHECK(xonly_pubkeys == NULL || n_xonly_pubkeys >= 1);
ARG_CHECK((plain_pubkeys != NULL) || (xonly_pubkeys != NULL));
ARG_CHECK((n_plain_pubkeys + n_xonly_pubkeys) >= 1);
ARG_CHECK(outpoint_smallest36 != NULL);

/* Compute input public keys sum: A_sum = A_1 + A_2 + ... + A_n */
secp256k1_gej_set_infinity(&A_sum_gej);
for (i = 0; i < n_plain_pubkeys; i++) {
secp256k1_pubkey_load(ctx, &addend, &plain_pubkeys[i]);
secp256k1_gej_add_ge(&A_sum_gej, &A_sum_gej, &addend);
}
for (i = 0; i < n_xonly_pubkeys; i++) {
secp256k1_xonly_pubkey_load(ctx, &addend, &xonly_pubkeys[i]);
secp256k1_gej_add_ge(&A_sum_gej, &A_sum_gej, &addend);
}
if (secp256k1_gej_is_infinity(&A_sum_gej)) {
/* TODO: do we need a special error return code for this case? */
return 0;
}
secp256k1_ge_set_gej(&A_sum_ge, &A_sum_gej);

/* Compute input_hash = hash(outpoint_L || A_sum) */
secp256k1_silentpayments_calculate_input_hash(&input_hash_scalar, outpoint_smallest36, &A_sum_ge);

/* Compute A_tweaked = A_sum * input_hash */
if (!secp256k1_eckey_pubkey_tweak_mul(&A_sum_ge, &input_hash_scalar)) {
return 0;
}
secp256k1_pubkey_save(public_tweak_data, &A_sum_ge);

return 1;
}

/* TODO: implement functions for receiver side. */

#endif

0 comments on commit 2290e80

Please sign in to comment.