Skip to content

Commit 987d829

Browse files
theStackjosibake
authored andcommitted
silentpayments: add recipient label support
Add function for creating a label tweak. This requires a tagged hash function for labels. This function is used by the receiver for creating labels to be used for a) creating labelled addresses and b) to populate a labels cache when scanning. Add function for creating a labelled spend pubkey. This involves taking a label tweak, turning it into a public key and adding it to the spend public key. This function is used by the receiver to create a labelled silent payment address.
1 parent 14ca754 commit 987d829

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

include/secp256k1_silentpayments.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,51 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_sender_c
9393
size_t n_plain_seckeys
9494
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
9595

96+
/** Create Silent Payment label tweak and label.
97+
*
98+
* Given a recipient's scan private key b_scan and a label integer m, calculate
99+
* the corresponding label tweak and label:
100+
*
101+
* label_tweak = hash(b_scan || m)
102+
* label = label_tweak * G
103+
*
104+
* Returns: 1 if label tweak and label creation was successful. 0 if an error occured.
105+
* Args: ctx: pointer to a context object
106+
* Out: label_tweak: pointer to the resulting label tweak
107+
* In: receiver_scan_seckey: pointer to the receiver's scan private key
108+
* m: label integer (0 is used for change outputs)
109+
*/
110+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_label_tweak(
111+
const secp256k1_context *ctx,
112+
secp256k1_pubkey *label,
113+
unsigned char *label_tweak32,
114+
const unsigned char *receiver_scan_seckey,
115+
unsigned int m
116+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
117+
118+
/** Create Silent Payment labelled spend public key.
119+
*
120+
* Given a recipient's spend public key B_spend and a label, calculate
121+
* the corresponding serialized labelled spend public key:
122+
*
123+
* B_m = B_spend + label
124+
*
125+
* The result is used by the recipient to create a Silent Payment address, consisting
126+
* of the serialized and concatenated scan public key and (labelled) spend public key each.
127+
*
128+
* Returns: 1 if labelled spend public key creation was successful. 0 if an error occured.
129+
* Args: ctx: pointer to a context object
130+
* Out: l_addr_spend_pubkey33: pointer to the resulting labelled spend public key
131+
* In: receiver_spend_pubkey: pointer to the receiver's spend pubkey
132+
* label: pointer to the the receiver's label
133+
*/
134+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_labelled_spend_pubkey(
135+
const secp256k1_context *ctx,
136+
secp256k1_pubkey *labeled_spend_pubkey,
137+
const secp256k1_pubkey *receiver_spend_pubkey,
138+
const secp256k1_pubkey *label
139+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
140+
96141
#ifdef __cplusplus
97142
}
98143
#endif

src/modules/silentpayments/main_impl.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,69 @@ int secp256k1_silentpayments_sender_create_outputs(
263263
return 1;
264264
}
265265

266+
/** Set hash state to the BIP340 tagged hash midstate for "BIP0352/Label". */
267+
static void secp256k1_silentpayments_sha256_init_label(secp256k1_sha256* hash) {
268+
secp256k1_sha256_initialize(hash);
269+
hash->s[0] = 0x26b95d63ul;
270+
hash->s[1] = 0x8bf1b740ul;
271+
hash->s[2] = 0x10a5986ful;
272+
hash->s[3] = 0x06a387a5ul;
273+
hash->s[4] = 0x2d1c1c30ul;
274+
hash->s[5] = 0xd035951aul;
275+
hash->s[6] = 0x2d7f0f96ul;
276+
hash->s[7] = 0x29e3e0dbul;
277+
278+
hash->bytes = 64;
279+
}
280+
281+
int secp256k1_silentpayments_recipient_create_label_tweak(const secp256k1_context *ctx, secp256k1_pubkey *label, unsigned char *label_tweak32, const unsigned char *receiver_scan_seckey, unsigned int m) {
282+
secp256k1_sha256 hash;
283+
unsigned char m_serialized[4];
284+
285+
/* Sanity check inputs. */
286+
VERIFY_CHECK(ctx != NULL);
287+
(void)ctx;
288+
VERIFY_CHECK(label != NULL);
289+
VERIFY_CHECK(label_tweak32 != NULL);
290+
VERIFY_CHECK(receiver_scan_seckey != NULL);
291+
292+
/* Compute label_tweak = hash(ser_256(b_scan) || ser_32(m)) [sha256 with tag "BIP0352/Label"] */
293+
secp256k1_silentpayments_sha256_init_label(&hash);
294+
secp256k1_sha256_write(&hash, receiver_scan_seckey, 32);
295+
secp256k1_write_be32(m_serialized, m);
296+
secp256k1_sha256_write(&hash, m_serialized, sizeof(m_serialized));
297+
secp256k1_sha256_finalize(&hash, label_tweak32);
298+
299+
/* Compute label = label_tweak * G */
300+
if (!secp256k1_ec_pubkey_create(ctx, label, label_tweak32)) {
301+
return 0;
302+
}
303+
304+
return 1;
305+
}
306+
307+
int secp256k1_silentpayments_recipient_create_labelled_spend_pubkey(const secp256k1_context *ctx, secp256k1_pubkey *labeled_spend_pubkey, const secp256k1_pubkey *receiver_spend_pubkey, const secp256k1_pubkey *label) {
308+
secp256k1_ge B_m, label_addend;
309+
secp256k1_gej result_gej;
310+
secp256k1_ge result_ge;
311+
312+
/* Sanity check inputs. */
313+
VERIFY_CHECK(ctx != NULL);
314+
VERIFY_CHECK(labeled_spend_pubkey != NULL);
315+
VERIFY_CHECK(receiver_spend_pubkey != NULL);
316+
VERIFY_CHECK(label != NULL);
317+
318+
/* Calculate B_m = B_spend + label */
319+
secp256k1_pubkey_load(ctx, &B_m, receiver_spend_pubkey);
320+
secp256k1_pubkey_load(ctx, &label_addend, label);
321+
secp256k1_gej_set_ge(&result_gej, &B_m);
322+
secp256k1_gej_add_ge_var(&result_gej, &result_gej, &label_addend, NULL);
323+
324+
/* Serialize B_m */
325+
secp256k1_ge_set_gej(&result_ge, &result_gej);
326+
secp256k1_pubkey_save(labeled_spend_pubkey, &result_ge);
327+
328+
return 1;
329+
}
330+
266331
#endif

0 commit comments

Comments
 (0)