Skip to content

Commit 45e7835

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 651812d commit 45e7835

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

include/secp256k1_silentpayments.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,52 @@ 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 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: pointer to the resulting label public key
107+
* label_tweak32: pointer to the 32 byte label tweak
108+
* In: recipient_scan_key: pointer to the recipient's scan key
109+
* m: label integer (0 is used for change outputs)
110+
*/
111+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_label_tweak(
112+
const secp256k1_context *ctx,
113+
secp256k1_pubkey *label,
114+
unsigned char *label_tweak32,
115+
const unsigned char *recipient_scan_key,
116+
unsigned int m
117+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
118+
119+
/** Create Silent Payment labelled spend public key.
120+
*
121+
* Given a recipient's spend public key B_spend and a label, calculate
122+
* the corresponding serialized labelled spend public key:
123+
*
124+
* B_m = B_spend + label
125+
*
126+
* The result is used by the recipient to create a Silent Payment address, consisting
127+
* of the serialized and concatenated scan public key and (labelled) spend public key each.
128+
*
129+
* Returns: 1 if labelled spend public key creation was successful. 0 if an error occured.
130+
* Args: ctx: pointer to a context object
131+
* Out: labelled_spend_pubkey: pointer to the resulting labelled spend public key
132+
* In: recipient_spend_pubkey: pointer to the recipient's spend pubkey
133+
* label: pointer to the the recipient's label public key
134+
*/
135+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_labelled_spend_pubkey(
136+
const secp256k1_context *ctx,
137+
secp256k1_pubkey *labelled_spend_pubkey,
138+
const secp256k1_pubkey *recipient_spend_pubkey,
139+
const secp256k1_pubkey *label
140+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
141+
96142
#ifdef __cplusplus
97143
}
98144
#endif

src/modules/silentpayments/main_impl.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,68 @@ int secp256k1_silentpayments_sender_create_outputs(
256256
return 1;
257257
}
258258

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

0 commit comments

Comments
 (0)