Coverage Report

Created: 2026-07-30 14:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/secp256k1/include/secp256k1_silentpayments.h
Line
Count
Source
1
#ifndef SECP256K1_SILENTPAYMENTS_H
2
#define SECP256K1_SILENTPAYMENTS_H
3
4
#include <stdint.h>
5
#include "secp256k1.h"
6
#include "secp256k1_extrakeys.h"
7
8
#ifdef __cplusplus
9
extern "C" {
10
#endif
11
12
/** This module provides an implementation for Silent Payments, as specified in
13
 *  BIP352. This particularly involves the creation of input tweak data by
14
 *  summing up secret or public keys and the derivation of a shared secret using
15
 *  Elliptic Curve Diffie-Hellman. Combined are either:
16
 *    - spender's secret keys and recipient's public key (a * B, sender side)
17
 *    - spender's public keys and recipient's secret key (A * b, recipient side)
18
 *  With this result, the necessary key material for ultimately creating/scanning
19
 *  or spending Silent Payments outputs can be determined.
20
 *
21
 *  Note that this module is _not_ a full implementation of BIP352, as it
22
 *  inherently doesn't deal with higher-level concepts like addresses, output
23
 *  script types or transactions. The intent is to provide a module for
24
 *  abstracting away the elliptic-curve operations required for the protocol. For
25
 *  any wallet software already using libsecp256k1, this API should provide all
26
 *  the functions needed for a Silent Payments implementation without requiring
27
 *  any further elliptic-curve operations from the wallet.
28
 */
29
30
/* Maximum number of Silent Payments recipients per group (i.e.
31
 * recipients sharing the same scan public key) as per BIP-352 */
32
0
#define SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT 2323
33
34
/** The data from a single recipient address
35
 *
36
 *  This struct serves as an input argument to `silentpayments_sender_create_outputs`.
37
 *
38
 *  `index` must be set to the position (starting with 0) of this recipient in the
39
 *  `recipients` array passed to `silentpayments_sender_create_outputs`. It is
40
 *  used to map the returned generated outputs back to the original recipient.
41
 *
42
 *  Note:
43
 *  The spend public key named `spend_pubkey` may have been optionally tweaked with
44
 *  a label by the recipient. Whether `spend_pubkey` has actually been tagged with
45
 *  a label is irrelevant for the sender. As a documentation convention in this API,
46
 *  `unlabeled_spend_pubkey` is used to indicate when the unlabeled spend public key
47
 *  must be used.
48
 */
49
typedef struct secp256k1_silentpayments_recipient {
50
    secp256k1_pubkey scan_pubkey;
51
    secp256k1_pubkey spend_pubkey;
52
    size_t index;
53
} secp256k1_silentpayments_recipient;
54
55
/** Create Silent Payments outputs for recipient(s).
56
 *
57
 *  Given a list of n secret keys a_1...a_n (one for each Silent Payments
58
 *  eligible input to spend), a serialized outpoint, and a list of recipients,
59
 *  create the taproot outputs. Inputs with conditional branches or multiple
60
 *  public keys are excluded from Silent Payments eligible inputs; see BIP352
61
 *  for more information.
62
 *
63
 *  `outpoint_smallest36` refers to the smallest outpoint lexicographically
64
 *  from the transaction inputs (both Silent Payments eligible and non-eligible
65
 *  inputs). This value MUST be the smallest outpoint out of all of the
66
 *  transaction inputs, otherwise the recipient will be unable to find the
67
 *  payment. Determining the smallest outpoint from the list of transaction
68
 *  inputs is the responsibility of the caller. It is strongly recommended
69
 *  that implementations ensure they are doing this correctly by using the
70
 *  test vectors from BIP352.
71
 *
72
 *  When creating more than one generated output, all of the generated outputs
73
 *  MUST be included in the final transaction. Dropping any of the generated
74
 *  outputs from the final transaction may make all or some of the outputs
75
 *  unfindable by the recipient.
76
 *
77
 *  Returns: 1 if creation of outputs was successful.
78
 *           0 on failure. This is expected only with an adversarially chosen
79
 *           recipient spend key. Specifically, failure occurs when:
80
 *             - Input secret keys sum to 0
81
 *               (negligible probability if at least one of the input secret
82
 *               keys is uniformly random and independent of all other keys)
83
 *             - A hash output is not a valid scalar (negligible probability
84
 *               per hash evaluation)
85
 *             - Any group (i.e. recipients sharing the same scan public key) exceeds
86
 *               the protocol limit SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT
87
 *
88
 *  Args:                ctx: pointer to a context object
89
 *                            (not secp256k1_context_static).
90
 *  Out:   generated_outputs: pointer to an array of pointers to xonly public keys,
91
 *                            one per recipient.
92
 *                            The outputs are ordered to match the original
93
 *                            ordering of the recipient objects, i.e.,
94
 *                            `generated_outputs[0]` is the generated output
95
 *                            for the `secp256k1_silentpayments_recipient` object
96
 *                            with index = 0.
97
 *  In:           recipients: pointer to an array of pointers to Silent Payments
98
 *                            recipients, where each recipient is a scan public
99
 *                            key, a spend public key, and an index indicating
100
 *                            its position in the original ordering. The
101
 *                            recipient array will be grouped by scan public key
102
 *                            in place (as specified in BIP0352), but generated
103
 *                            outputs are saved in the `generated_outputs` array
104
 *                            to match the original ordering (using the index
105
 *                            field). This ensures the caller is able to match
106
 *                            the generated outputs to the correct Silent
107
 *                            Payments addresses. The same recipient can be
108
 *                            passed multiple times to create multiple outputs
109
 *                            for the same recipient.
110
 *              n_recipients: the size of the recipients array.
111
 *       outpoint_smallest36: serialized (36-byte) smallest outpoint
112
 *                            (lexicographically) from the transaction inputs
113
 *                  keypairs: pointer to an array of pointers to taproot
114
 *                            keypair inputs (can be NULL if no secret keys
115
 *                            of taproot inputs are used)
116
 *                n_keypairs: the size of the keypairs array.
117
 *                   seckeys: pointer to an array of pointers to 32-byte
118
 *                            secret keys of non-taproot inputs (can be NULL
119
 *                            if no secret keys of non-taproot inputs are
120
 *                            used)
121
 *                 n_seckeys: the size of the seckeys array.
122
 */
123
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_sender_create_outputs(
124
    const secp256k1_context *ctx,
125
    secp256k1_xonly_pubkey **generated_outputs,
126
    const secp256k1_silentpayments_recipient **recipients,
127
    size_t n_recipients,
128
    const unsigned char *outpoint_smallest36,
129
    const secp256k1_keypair * const *keypairs,
130
    size_t n_keypairs,
131
    const unsigned char * const *seckeys,
132
    size_t n_seckeys
133
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
134
135
/** Opaque data structure that holds a Silent Payments label.
136
 *
137
 *  Guaranteed to be 68 bytes in size. Serialized and parsed with
138
 *  `secp256k1_silentpayments_recipient_label_serialize` and
139
 *  `secp256k1_silentpayments_recipient_label_parse`.
140
 */
141
typedef struct secp256k1_silentpayments_label {
142
    unsigned char data[68];
143
} secp256k1_silentpayments_label;
144
145
/** Parse a Silent Payments label.
146
 *
147
 *  Returns: 1 when the label could be parsed, 0 otherwise.
148
 *  Args:    ctx: pointer to a context object
149
 *  Out:   label: pointer to a label object
150
 *  In:     in33: pointer to the 33-byte label to be parsed
151
 */
152
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_label_parse(
153
    const secp256k1_context *ctx,
154
    secp256k1_silentpayments_label *label,
155
    const unsigned char *in33
156
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
157
158
/** Serialize a Silent Payments label
159
 *
160
 *  Returns: 1 always
161
 *  Args:    ctx: pointer to a context object
162
 *  Out:   out33: pointer to a 33-byte array to store the serialized label
163
 *  In:    label: pointer to the label
164
 */
165
SECP256K1_API int secp256k1_silentpayments_recipient_label_serialize(
166
    const secp256k1_context *ctx,
167
    unsigned char *out33,
168
    const secp256k1_silentpayments_label *label
169
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
170
171
/** Create Silent Payments label tweak and label.
172
 *
173
 *  Given a recipient's 32 byte scan key and a label integer m, calculate the
174
 *  corresponding label tweak and label:
175
 *
176
 *      label_tweak = hash(scan_key || m)
177
 *            label = label_tweak * G
178
 *
179
 *  Returns: 1 if label tweak and label creation was successful.
180
 *           0 if scan_key32 is invalid or the hash output label_tweak32 is
181
 *             not a valid scalar (negligible probability per hash evaluation).
182
 *
183
 * WARNING: Creating a large number of labels may significantly degrade
184
 * scanning performance in certain Silent Payments wallet implementations,
185
 * such as light clients. The scanning function provided in this module,
186
 * which is designed for full nodes, performs consistently even with hundreds
187
 * of thousands of labels. Other implementations may not share this property
188
 * or may be unable to use it due to lacking full transaction data.
189
 *
190
 * To maximize wallet interoperability, it is recommended to create only
191
 * the change label (m = 0) and avoid distributing labeled addresses.
192
 *
193
 *  Args:                ctx: pointer to a context object
194
 *                            (not secp256k1_context_static)
195
 *  Out:               label: pointer to the resulting label
196
 *             label_tweak32: pointer to the 32 byte label tweak
197
 *  In:           scan_key32: pointer to the recipient's 32 byte scan key
198
 *                         m: integer for the m-th label (0 is used for change outputs)
199
 */
200
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_label_create(
201
    const secp256k1_context *ctx,
202
    secp256k1_silentpayments_label *label,
203
    unsigned char *label_tweak32,
204
    const unsigned char *scan_key32,
205
    uint32_t m
206
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
207
208
/** Create Silent Payments labeled spend public key.
209
 *
210
 *  Given a recipient's spend public key and a label, calculate the
211
 *  corresponding labeled spend public key:
212
 *
213
 *      labeled_spend_pubkey = unlabeled_spend_pubkey + label
214
 *
215
 *  The result is used by the recipient to create a Silent Payments address,
216
 *  consisting of the serialized and concatenated scan public key and
217
 *  (labeled) spend public key.
218
 *
219
 *  Returns: 1 if labeled spend public key creation was successful.
220
 *           0 if spend pubkey and label sum to zero (negligible probability for
221
 *             labels created according to BIP352).
222
 *
223
 *  Args:                    ctx: pointer to a context object
224
 *  Out:    labeled_spend_pubkey: pointer to the resulting labeled spend public key
225
 *  In:   unlabeled_spend_pubkey: pointer to the recipient's unlabeled spend public key
226
 *                         label: pointer to the recipient's label
227
 */
228
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_labeled_spend_pubkey(
229
    const secp256k1_context *ctx,
230
    secp256k1_pubkey *labeled_spend_pubkey,
231
    const secp256k1_pubkey *unlabeled_spend_pubkey,
232
    const secp256k1_silentpayments_label *label
233
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
234
235
/** Opaque data structure that holds Silent Payments prevouts summary data.
236
 *
237
 *  The exact representation of data inside is implementation defined and not
238
 *  guaranteed to be portable between different platforms or versions. It is
239
 *  however guaranteed to be 101 bytes in size, and can be safely copied/moved.
240
 *  This structure does not contain secret data. It can be created with
241
 *  `secp256k1_silentpayments_recipient_prevouts_summary_create`.
242
 */
243
typedef struct secp256k1_silentpayments_prevouts_summary {
244
    unsigned char data[101];
245
} secp256k1_silentpayments_prevouts_summary;
246
247
/** Compute Silent Payments prevouts summary from prevout public keys and transaction
248
 *  inputs.
249
 *
250
 *  Given a list of n public keys A_1...A_n (one for each Silent Payments
251
 *  eligible input to spend) and a serialized outpoint_smallest36, create a
252
 *  `prevouts_summary` object. This object summarizes the prevout data from the
253
 *  transaction inputs needed for scanning.
254
 *
255
 *  `outpoint_smallest36` refers to the smallest outpoint lexicographically
256
 *  from the transaction inputs (both Silent Payments eligible and non-eligible
257
 *  inputs). This value MUST be the smallest outpoint out of all of the
258
 *  transaction inputs, otherwise the recipient will be unable to find the
259
 *  payment.
260
 *
261
 *  The public keys have to be passed in via two different parameter pairs, one
262
 *  for regular and one for x-only public keys, in order to avoid the need of
263
 *  users converting to a common public key format before calling this function.
264
 *  The resulting data can be used for scanning on the recipient side.
265
 *
266
 *  Returns: 1 if prevouts summary creation was successful.
267
 *           0 if the transaction is not a Silent Payments transaction.
268
 *
269
 *  Args:                 ctx: pointer to a context object
270
 *  Out:     prevouts_summary: pointer to prevouts_summary object containing the
271
 *                             summed public key and input_hash.
272
 *  In:   outpoint_smallest36: serialized smallest outpoint (lexicographically)
273
 *                             from the transaction inputs
274
 *              xonly_pubkeys: pointer to an array of pointers to taproot
275
 *                             x-only public keys (can be NULL if no taproot
276
 *                             inputs are used)
277
 *            n_xonly_pubkeys: the size of the xonly_pubkeys array.
278
 *                    pubkeys: pointer to an array of pointers to non-taproot
279
 *                             public keys (can be NULL if no non-taproot
280
 *                             inputs are used)
281
 *                  n_pubkeys: the size of the pubkeys array.
282
 */
283
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_prevouts_summary_create(
284
    const secp256k1_context *ctx,
285
    secp256k1_silentpayments_prevouts_summary *prevouts_summary,
286
    const unsigned char *outpoint_smallest36,
287
    const secp256k1_xonly_pubkey * const *xonly_pubkeys,
288
    size_t n_xonly_pubkeys,
289
    const secp256k1_pubkey * const *pubkeys,
290
    size_t n_pubkeys
291
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
292
293
/** Type of callback function for label lookups
294
 *
295
 *  A function of this type will be used to retrieve the label tweak for a given
296
 *  label during scanning. A typical implementation will perform a lookup in a
297
 *  key-value store called the "label cache".
298
 *
299
 *  For creating the label cache data,
300
 *  `secp256k1_silentpayments_recipient_label_create` and
301
 *  `secp256k1_silentpayments_recipient_label_serialize` can be used.
302
 *
303
 *  Returns: pointer to the 32-byte label tweak if there is a match.
304
 *           NULL pointer if there is no match.
305
 *
306
 *  In:         label: pointer to the serialized 33-byte label to check
307
 *                     (computed during scanning)
308
 *      label_context: pointer to the recipient's label cache.
309
 */
310
typedef const unsigned char* (*secp256k1_silentpayments_label_lookup)(const unsigned char* label33, const void* label_context);
311
312
/** Found outputs struct
313
 *
314
 *  Struct for holding a found output along with data needed to spend it later.
315
 *
316
 *            output: the x-only public key for the taproot output
317
 *             tweak: the 32-byte tweak needed to spend the output
318
 *  found_with_label: boolean value to indicate if the output was sent to a
319
 *                    labeled address. If true, label will be set to a valid value.
320
 *             label: the label used. If found_with_label = false, this is set to
321
 *                    an invalid value.
322
 */
323
typedef struct secp256k1_silentpayments_found_output {
324
    secp256k1_xonly_pubkey output;
325
    unsigned char tweak[32];
326
    int found_with_label;
327
    secp256k1_silentpayments_label label;
328
} secp256k1_silentpayments_found_output;
329
330
/** Scan for Silent Payments transaction outputs.
331
 *
332
 *  Given a prevouts_summary object, a recipient's 32 byte scan key and spend public key,
333
 *  and the relevant transaction outputs, scan for outputs belonging to
334
 *  the recipient and return the tweak(s) needed for spending the output(s). An
335
 *  optional label_lookup callback function and label_context can be passed if
336
 *  the recipient uses labels. This allows for checking if a label exists in
337
 *  the recipients label cache and retrieving the label tweak during scanning.
338
 *
339
 *  If used, the `label_lookup` function must return a pointer to a 32-byte label
340
 *  tweak if the label is found, or NULL otherwise. The returned pointer must remain
341
 *  valid until the next call to `label_lookup` or until the function returns,
342
 *  whichever comes first. It is not retained beyond that.
343
 *
344
 *  For creating the label cache, `secp256k1_silentpayments_recipient_label_create`
345
 *  and `secp256k1_silentpayments_recipient_label_serialize` can be used.
346
 *
347
 *  Note:
348
 *  Scanning is bounded by SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT and may
349
 *  miss outputs if a transaction contains more outputs for a single scan public
350
 *  key group than this limit.
351
 *
352
 *  Returns: 1 if output scanning was successful.
353
 *           0 if the transaction is not a Silent Payments transaction,
354
 *             or if the arguments are invalid.
355
 *
356
 *  Args:                   ctx: pointer to a context object
357
 *  Out:          found_outputs: pointer to an array of pointers to found
358
 *                               output objects. The found outputs array MUST
359
 *                               have the same length as the tx_outputs array.
360
 *              n_found_outputs: pointer to an integer indicating the final
361
 *                               size of the found outputs array. This number
362
 *                               represents the number of outputs found while
363
 *                               scanning (0 if none are found). Can't be larger than
364
 *                               SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT.
365
 *  In:              tx_outputs: pointer to the transaction's x-only public key outputs,
366
 *                               in their original transaction (vout) order
367
 *                 n_tx_outputs: the size of the tx_outputs array.
368
 *                   scan_key32: pointer to the recipient's 32 byte scan key. The scan
369
 *                               key is valid if it passes secp256k1_ec_seckey_verify
370
 *             prevouts_summary: pointer to the transaction prevouts summary data (see
371
 *                               `secp256k1_silentpayments_recipient_prevouts_summary_create`).
372
 *       unlabeled_spend_pubkey: pointer to the recipient's unlabeled spend public key
373
 *                 label_lookup: pointer to a callback function for looking up
374
 *                               a label value. This function takes a serialized 33-byte
375
 *                               label as an argument and returns a pointer to the
376
 *                               32-byte label tweak if the label exists, otherwise
377
 *                               returns a NULL pointer (NULL if labels are not
378
 *                               used)
379
 *                label_context: pointer to a label context object (NULL if
380
 *                               labels are not used or context is not needed)
381
 */
382
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_scan_outputs(
383
    const secp256k1_context *ctx,
384
    secp256k1_silentpayments_found_output **found_outputs,
385
    uint32_t *n_found_outputs,
386
    const secp256k1_xonly_pubkey * const *tx_outputs,
387
    size_t n_tx_outputs,
388
    const unsigned char *scan_key32,
389
    const secp256k1_silentpayments_prevouts_summary *prevouts_summary,
390
    const secp256k1_pubkey *unlabeled_spend_pubkey,
391
    secp256k1_silentpayments_label_lookup label_lookup,
392
    const void *label_context
393
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8);
394
395
#ifdef __cplusplus
396
}
397
#endif
398
399
#endif /* SECP256K1_SILENTPAYMENTS_H */