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