1
1
#ifndef SECP256K1_SILENTPAYMENTS_H
2
2
#define SECP256K1_SILENTPAYMENTS_H
3
3
4
+ #include <stdint.h>
4
5
#include "secp256k1.h"
5
6
#include "secp256k1_extrakeys.h"
6
7
@@ -26,6 +27,7 @@ extern "C" {
26
27
* any further elliptic-curve operations from the wallet.
27
28
*/
28
29
30
+ static const unsigned char secp256k1_silentpayments_public_data_magic [4 ] = { 0xa7 , 0x1c , 0xd3 , 0x5e };
29
31
30
32
/** The data from a single recipient address
31
33
*
@@ -171,6 +173,262 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipien
171
173
const secp256k1_pubkey * label
172
174
) SECP256K1_ARG_NONNULL (1 ) SECP256K1_ARG_NONNULL (2 ) SECP256K1_ARG_NONNULL (3 ) SECP256K1_ARG_NONNULL (4 );
173
175
176
+ /** Opaque data structure that holds silent payments public input data.
177
+ *
178
+ * This structure does not contain secret data. Guaranteed to be 101 bytes in
179
+ * size. It can be safely copied/moved. Created with
180
+ * `secp256k1_silentpayments_recipient_public_data_create`. Can be serialized as a
181
+ * compressed public key using
182
+ * `secp256k1_silentpayments_recipient_public_data_serialize`. The serialization is
183
+ * intended for sending the public input data to light clients. Light clients
184
+ * can use this serialization with
185
+ * `secp256k1_silentpayments_recipient_public_data_parse`.
186
+ */
187
+ typedef struct secp256k1_silentpayments_recipient_public_data {
188
+ unsigned char data [101 ];
189
+ } secp256k1_silentpayments_recipient_public_data ;
190
+
191
+ /** Compute Silent Payment public data from input public keys and transaction
192
+ * inputs.
193
+ *
194
+ * Given a list of n public keys A_1...A_n (one for each silent payment
195
+ * eligible input to spend) and a serialized outpoint_smallest36, create a
196
+ * `public_data` object. This object summarizes the public data from the
197
+ * transaction inputs needed for scanning.
198
+ *
199
+ * `outpoint_smallest36` refers to the smallest outpoint lexicographically
200
+ * from the transaction inputs (both silent payments eligible and non-eligible
201
+ * inputs). This value MUST be the smallest outpoint out of all of the
202
+ * transaction inputs, otherwise the recipient will be unable to find the
203
+ * payment.
204
+ *
205
+ * The public keys have to be passed in via two different parameter pairs, one
206
+ * for regular and one for x-only public keys, in order to avoid the need of
207
+ * users converting to a common pubkey format before calling this function.
208
+ * The resulting data can be used for scanning on the recipient side, or
209
+ * stored in an index for later use (e.g., wallet rescanning, sending data to
210
+ * light clients).
211
+ *
212
+ * If calling this function for simply aggregating the public transaction data
213
+ * for later use, the caller can save the result with
214
+ * `silentpayments_recipient_public_data_serialize`.
215
+ *
216
+ * Returns: 1 if public data creation was successful.
217
+ * 0 if the input public keys sum to zero,
218
+ * or the input_hash is an invalid scalar (statistically improbable).
219
+ * Args: ctx: pointer to a context object
220
+ * Out: public_data: pointer to public_data object containing the
221
+ * summed public key and input_hash.
222
+ * In: outpoint_smallest36: serialized smallest outpoint (lexicographically)
223
+ * from the transaction inputs
224
+ * xonly_pubkeys: pointer to an array of pointers to taproot
225
+ * x-only public keys (can be NULL if no taproot
226
+ * inputs are used)
227
+ * n_xonly_pubkeys: the number of taproot input public keys
228
+ * plain_pubkeys: pointer to an array of pointers to non-taproot
229
+ * public keys (can be NULL if no non-taproot
230
+ * inputs are used)
231
+ * n_plain_pubkeys: the number of non-taproot input public keys
232
+ */
233
+ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_public_data_create (
234
+ const secp256k1_context * ctx ,
235
+ secp256k1_silentpayments_recipient_public_data * public_data ,
236
+ const unsigned char * outpoint_smallest36 ,
237
+ const secp256k1_xonly_pubkey * const * xonly_pubkeys ,
238
+ size_t n_xonly_pubkeys ,
239
+ const secp256k1_pubkey * const * plain_pubkeys ,
240
+ size_t n_plain_pubkeys
241
+ ) SECP256K1_ARG_NONNULL (1 ) SECP256K1_ARG_NONNULL (2 ) SECP256K1_ARG_NONNULL (3 );
242
+
243
+ /** Serialize a silentpayments_recipient_public_data object into a 33-byte sequence.
244
+ *
245
+ * Returns: 1 always.
246
+ *
247
+ * Args: ctx: pointer to a context object
248
+ * Out: output33: pointer to a 33-byte array to place the serialized
249
+ * `silentpayments_recipient_public_data` in
250
+ * In: public_data: pointer to an initialized silentpayments_recipient_public_data
251
+ * object
252
+ */
253
+ SECP256K1_API int secp256k1_silentpayments_recipient_public_data_serialize (
254
+ const secp256k1_context * ctx ,
255
+ unsigned char * output33 ,
256
+ const secp256k1_silentpayments_recipient_public_data * public_data
257
+ ) SECP256K1_ARG_NONNULL (1 ) SECP256K1_ARG_NONNULL (2 ) SECP256K1_ARG_NONNULL (3 );
258
+
259
+ /** Parse a 33-byte sequence into a silentpayments_recipients_public_data object.
260
+ *
261
+ * Returns: 1 if the data was able to be parsed.
262
+ * 0 if the sequence is invalid (e.g., does not represent a valid
263
+ * public key).
264
+ *
265
+ * Args: ctx: pointer to a context object.
266
+ * Out: public_data: pointer to a silentpayments_recipient_public_data object. If 1 is
267
+ * returned, it is set to a parsed version of input33.
268
+ * In: input33: pointer to a serialized silentpayments_recipient_public_data.
269
+ */
270
+ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_public_data_parse (
271
+ const secp256k1_context * ctx ,
272
+ secp256k1_silentpayments_recipient_public_data * public_data ,
273
+ const unsigned char * input33
274
+ ) SECP256K1_ARG_NONNULL (1 ) SECP256K1_ARG_NONNULL (2 ) SECP256K1_ARG_NONNULL (3 );
275
+
276
+ /** Callback function for label lookups
277
+ *
278
+ * This function is implemented by the recipient to check if a value exists in
279
+ * the recipients label cache during scanning.
280
+ *
281
+ * For creating the labels cache data,
282
+ * `secp256k1_silentpayments_recipient_create_label` can be used.
283
+ *
284
+ * Returns: pointer to the 32-byte label tweak if there is a match.
285
+ * NULL pointer if there is no match.
286
+ *
287
+ * In: label: pointer to the label pubkey to check (computed during
288
+ * scanning)
289
+ * label_context: pointer to the recipients label cache.
290
+ */
291
+ typedef const unsigned char * (* secp256k1_silentpayments_label_lookup )(const unsigned char * label33 , const void * label_context );
292
+
293
+ /** Found outputs struct
294
+ *
295
+ * Struct for holding a found output along with data needed to spend it later.
296
+ *
297
+ * output: the x-only public key for the taproot output
298
+ * tweak: the 32-byte tweak needed to spend the output
299
+ * found_with_label: boolean value to indicate if the output was sent to a
300
+ * labeled address. If true, label will be set with a valid
301
+ * public key.
302
+ * label: public key representing the label used.
303
+ * If found_with_label = false, this is set to an invalid
304
+ * public key.
305
+ */
306
+ typedef struct secp256k1_silentpayments_found_output {
307
+ secp256k1_xonly_pubkey output ;
308
+ unsigned char tweak [32 ];
309
+ int found_with_label ;
310
+ secp256k1_pubkey label ;
311
+ } secp256k1_silentpayments_found_output ;
312
+
313
+ /** Scan for Silent Payment transaction outputs.
314
+ *
315
+ * Given a public_data object, a recipient's 32 byte scan key and spend public key,
316
+ * and the relevant transaction outputs, scan for outputs belonging to
317
+ * the recipient and return the tweak(s) needed for spending the output(s). An
318
+ * optional label_lookup callback function and label_context can be passed if
319
+ * the recipient uses labels. This allows for checking if a label exists in
320
+ * the recipients label cache and retrieving the label tweak during scanning.
321
+ *
322
+ * If used, the `label_lookup` function must return a pointer to a 32-byte label
323
+ * tweak if the label is found, or NULL otherwise. The returned pointer must remain
324
+ * valid until the next call to `label_lookup` or until the function returns,
325
+ * whichever comes first. It is not retained beyond that.
326
+ *
327
+ * For the labels cache, `secp256k1_silentpayments_recipient_create_label`
328
+ * can be used.
329
+ *
330
+ * Returns: 1 if output scanning was successful.
331
+ * 0 if any combination of the shared secret, label and spend pubkey
332
+ * sum to zero (statistically improbable).
333
+ *
334
+ * Args: ctx: pointer to a context object
335
+ * Out: found_outputs: pointer to an array of pointers to found
336
+ * output objects. The found outputs array MUST
337
+ * be initialized to be the same length as the
338
+ * tx_outputs array
339
+ * n_found_outputs: pointer to an integer indicating the final
340
+ * size of the found outputs array. This number
341
+ * represents the number of outputs found while
342
+ * scanning (0 if none are found)
343
+ * In: tx_outputs: pointer to the tx's x-only public key outputs
344
+ * n_tx_outputs: the number of tx_outputs being scanned
345
+ * recipient_scan_key32: pointer to the recipient's 32 byte scan key
346
+ * public_data: pointer to the transaction public data
347
+ * (see `_recipient_public_data_create`).
348
+ * unlabeled_spend_pubkey: pointer to the recipient's unlabeled spend pubkey
349
+ * label_lookup: pointer to a callback function for looking up
350
+ * a label value. This function takes a label
351
+ * pubkey as an argument and returns a pointer to
352
+ * the label tweak if the label exists, otherwise
353
+ * returns a NULL pointer (NULL if labels are not
354
+ * used)
355
+ * label_context: pointer to a label context object (NULL if
356
+ * labels are not used or context is not needed)
357
+ */
358
+ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_scan_outputs (
359
+ const secp256k1_context * ctx ,
360
+ secp256k1_silentpayments_found_output * * found_outputs ,
361
+ size_t * n_found_outputs ,
362
+ const secp256k1_xonly_pubkey * const * tx_outputs ,
363
+ size_t n_tx_outputs ,
364
+ const unsigned char * recipient_scan_key32 ,
365
+ const secp256k1_silentpayments_recipient_public_data * public_data ,
366
+ const secp256k1_pubkey * unlabeled_spend_pubkey ,
367
+ const secp256k1_silentpayments_label_lookup label_lookup ,
368
+ const void * label_context
369
+ ) SECP256K1_ARG_NONNULL (1 ) SECP256K1_ARG_NONNULL (2 ) SECP256K1_ARG_NONNULL (3 ) SECP256K1_ARG_NONNULL (4 )
370
+ SECP256K1_ARG_NONNULL (6 ) SECP256K1_ARG_NONNULL (7 ) SECP256K1_ARG_NONNULL (8 );
371
+
372
+ /** Create Silent Payment shared secret.
373
+ *
374
+ * Given the public input data (secp256k1_silentpayments_recipient_public_data),
375
+ * and the recipient's 32 byte scan key, calculate the shared secret.
376
+ *
377
+ * The resulting shared secret is needed as input for creating silent payments
378
+ * outputs belonging to the same recipient scan public key. This function is
379
+ * intended for light clients, i.e., scenarios where the caller does not have
380
+ * access to the full transaction. If the caller does have access to the full
381
+ * transaction, `secp256k1_silentpayments_recipient_scan_outputs` should be
382
+ * used instead.
383
+ *
384
+ * Returns: 1 if shared secret creation was successful.
385
+ * 0 if the recipient scan key is invalid.
386
+ * Args: ctx: pointer to a context object
387
+ * Out: shared_secret33: pointer to the resulting 33-byte shared secret
388
+ * In: recipient_scan_key32: pointer to the recipient's 32 byte scan key
389
+ * public_data: pointer to the public_data object, loaded using
390
+ * `_recipient_public_data_parse`
391
+ */
392
+ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_shared_secret (
393
+ const secp256k1_context * ctx ,
394
+ unsigned char * shared_secret33 ,
395
+ const unsigned char * recipient_scan_key32 ,
396
+ const secp256k1_silentpayments_recipient_public_data * public_data
397
+ ) SECP256K1_ARG_NONNULL (1 ) SECP256K1_ARG_NONNULL (2 ) SECP256K1_ARG_NONNULL (3 ) SECP256K1_ARG_NONNULL (4 );
398
+
399
+ /** Create Silent Payment output public key.
400
+ *
401
+ * Given a shared_secret, a public key B_spend, and an output counter k,
402
+ * create an output public key.
403
+ *
404
+ * This function is used by the recipient when scanning for outputs without
405
+ * access to the transaction outputs (e.g., using BIP158 block filters). When
406
+ * scanning with this function, it is the scanners responsibility to determine
407
+ * if the generated output exists in a block before proceeding to the next
408
+ * value of `k`.
409
+ *
410
+ * Returns: 1 if output creation was successful.
411
+ * 0 if hash(shared secret || k) results in an invalid scalar
412
+ * (statistically improbable).
413
+ * Args: ctx: pointer to a context object
414
+ * Out: output_xonly: pointer to the resulting output x-only pubkey
415
+ * In: shared_secret33: shared secret, derived from either sender's
416
+ * or recipient's perspective with routines from
417
+ * above
418
+ * spend_pubkey: pointer to the recipient's spend pubkey
419
+ * (labeled or unlabeled)
420
+ * k: output counter (initially set to 0, must be
421
+ * incremented for each additional output created
422
+ * or after each output found when scanning)
423
+ */
424
+ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_output_pubkey (
425
+ const secp256k1_context * ctx ,
426
+ secp256k1_xonly_pubkey * output_xonly ,
427
+ const unsigned char * shared_secret33 ,
428
+ const secp256k1_pubkey * spend_pubkey ,
429
+ const uint32_t k
430
+ ) SECP256K1_ARG_NONNULL (1 ) SECP256K1_ARG_NONNULL (2 ) SECP256K1_ARG_NONNULL (3 ) SECP256K1_ARG_NONNULL (4 );
431
+
174
432
#ifdef __cplusplus
175
433
}
176
434
#endif
0 commit comments