Skip to content

Commit 64a451e

Browse files
committed
silentpayments: implement output pubkey creation (both sender and receiver)
Labels are not supported yet, the corresponding parameter label_tweak32 must be set to NULL right now.
1 parent 8b1f06b commit 64a451e

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

include/secp256k1_silentpayments.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,33 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_receive_
143143
const unsigned char *receiver_scan_seckey
144144
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
145145

146+
/** Create Silent Payment output public key (both for sender and receiver).
147+
*
148+
* Given a shared_secret, a recipient's spend public key B_spend, and an
149+
* output counter k, calculate the corresponding output public key:
150+
*
151+
* P_output = B_spend + sha256(shared_secret || ser_32(k)) * G
152+
*
153+
* Returns: 1 if outputs creation was successful. 0 if an error occured.
154+
* Args: ctx: pointer to a context object
155+
* Out: output_xonly_pubkey: pointer to the resulting output x-only pubkey
156+
* In: shared_secret33: shared secret, derived from either sender's
157+
* or receiver's perspective with routines from above
158+
* receiver_spend_pubkey: pointer to the receiver's spend pubkey
159+
* k: output counter (usually set to 0, should be increased for
160+
* every additional output to the same recipient)
161+
* label_tweak32: an optional 32-byte label tweak
162+
* (not supported yet, must be set to NULL right now)
163+
*/
164+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_output_pubkey(
165+
const secp256k1_context *ctx,
166+
secp256k1_xonly_pubkey *output_xonly_pubkey,
167+
const unsigned char *shared_secret33,
168+
const secp256k1_pubkey *receiver_spend_pubkey,
169+
unsigned int k,
170+
const unsigned char *label_tweak32
171+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
172+
146173
#ifdef __cplusplus
147174
}
148175
#endif

src/modules/silentpayments/main_impl.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../../../include/secp256k1_ecdh.h"
1111
#include "../../../include/secp256k1_extrakeys.h"
1212
#include "../../../include/secp256k1_silentpayments.h"
13+
#include "../../hash.h"
1314

1415
/* secp256k1_ecdh expects a hash function to be passed in or uses its default
1516
* hashing function. We don't want to hash the ECDH result, so we define a
@@ -202,4 +203,40 @@ int secp256k1_silentpayments_receive_create_shared_secret(const secp256k1_contex
202203
return 1;
203204
}
204205

206+
static void secp256k1_silentpayments_create_t_k(unsigned char *t_k, const unsigned char *shared_secret33, unsigned int k) {
207+
secp256k1_sha256 sha;
208+
unsigned char shared_secret_and_k[33+4];
209+
210+
/* Compute t_k = sha256(shared_secret || ser_32(k)) */
211+
memcpy(shared_secret_and_k, shared_secret33, 33);
212+
secp256k1_write_be32(shared_secret_and_k+33, k);
213+
secp256k1_sha256_initialize(&sha);
214+
secp256k1_sha256_write(&sha, shared_secret_and_k, sizeof(shared_secret_and_k));
215+
secp256k1_sha256_finalize(&sha, t_k);
216+
}
217+
218+
int secp256k1_silentpayments_create_output_pubkey(const secp256k1_context *ctx, secp256k1_xonly_pubkey *output_xonly_pubkey, const unsigned char *shared_secret33, const secp256k1_pubkey *receiver_spend_pubkey, unsigned int k, const unsigned char *label_tweak32) {
219+
secp256k1_pubkey P_output;
220+
unsigned char t_k[32];
221+
222+
/* Sanity check inputs */
223+
VERIFY_CHECK(ctx != NULL);
224+
ARG_CHECK(output_xonly_pubkey != NULL);
225+
ARG_CHECK(shared_secret33 != NULL);
226+
ARG_CHECK(receiver_spend_pubkey != NULL);
227+
ARG_CHECK(label_tweak32 == NULL); /* label tweaks are not supported yet */
228+
229+
/* Compute and return P_output = B_spend + t_k * G */
230+
secp256k1_silentpayments_create_t_k(t_k, shared_secret33, k);
231+
P_output = *receiver_spend_pubkey;
232+
if (!secp256k1_ec_pubkey_tweak_add(ctx, &P_output, t_k)) {
233+
return 0;
234+
}
235+
if (!secp256k1_xonly_pubkey_from_pubkey(ctx, output_xonly_pubkey, NULL, &P_output)) {
236+
return 0;
237+
}
238+
239+
return 1;
240+
}
241+
205242
#endif

0 commit comments

Comments
 (0)