Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#ifndef SECP256K1_SILENTPAYMENTS_H2#define SECP256K1_SILENTPAYMENTS_H4#include <stdint.h>5#include "secp256k1.h"6#include "secp256k1_extrakeys.h"8#ifdef __cplusplus9extern "C" {10#endif12/** This module provides an implementation for Silent Payments, as specified in13* BIP352. This particularly involves the creation of input tweak data by14* summing up secret or public keys and the derivation of a shared secret using15* 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/scanning19* or spending Silent Payments outputs can be determined.20*21* Note that this module is _not_ a full implementation of BIP352, as it22* inherently doesn't deal with higher-level concepts like addresses, output23* script types or transactions. The intent is to provide a module for24* abstracting away the elliptic-curve operations required for the protocol. For25* any wallet software already using libsecp256k1, this API should provide all26* the functions needed for a Silent Payments implementation without requiring27* any further elliptic-curve operations from the wallet.28*/30/* Maximum number of Silent Payments recipients per group (i.e.31* recipients sharing the same scan public key) as per BIP-352 */32#define SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT 232334/** The data from a single recipient address35*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 the39* `recipients` array passed to `silentpayments_sender_create_outputs`. It is40* 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 with44* a label by the recipient. Whether `spend_pubkey` has actually been tagged with45* 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 key47* must be used.48*/49typedef struct secp256k1_silentpayments_recipient {50secp256k1_pubkey scan_pubkey;51secp256k1_pubkey spend_pubkey;52size_t index;53} secp256k1_silentpayments_recipient;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 Payments58* eligible input to spend), a serialized outpoint, and a list of recipients,59* create the taproot outputs. Inputs with conditional branches or multiple60* public keys are excluded from Silent Payments eligible inputs; see BIP35261* for more information.62*63* `outpoint_smallest36` refers to the smallest outpoint lexicographically64* from the transaction inputs (both Silent Payments eligible and non-eligible65* inputs). This value MUST be the smallest outpoint out of all of the66* transaction inputs, otherwise the recipient will be unable to find the67* payment. Determining the smallest outpoint from the list of transaction68* inputs is the responsibility of the caller. It is strongly recommended69* that implementations ensure they are doing this correctly by using the70* test vectors from BIP352.71*72* When creating more than one generated output, all of the generated outputs73* MUST be included in the final transaction. Dropping any of the generated74* outputs from the final transaction may make all or some of the outputs75* unfindable by the recipient.76*77* Returns: 1 if creation of outputs was successful.78* 0 on failure, i.e., when one of the following occurs:79* - The size of any group (i.e. recipients sharing the same scan public key)80* exceeds the protocol limit SECP256K1_SILENTPAYMENTS_RECIPIENT_GROUP_LIMIT.81* - The sum of all input secret keys is 0.82* (This occurs only with negligible probability if at least one of the83* input secret keys is uniformly random and independent of all other keys.)84* - An invalid output public key is created. (This can only happen for an85* adversarially chosen recipient spend public key.)86*87* Args: ctx: pointer to a context object88* (not secp256k1_context_static).89* Out: generated_outputs: pointer to an array of pointers to xonly public keys,90* one per recipient.91* The outputs are ordered to match the original92* ordering of the recipient objects, i.e.,93* `generated_outputs[0]` is the generated output94* for the `secp256k1_silentpayments_recipient` object95* with index = 0.96* In: recipients: pointer to an array of pointers to Silent Payments97* recipients, where each recipient is a scan public98* key, a spend public key, and an index indicating99* its position in the original ordering. This function100* may reorder the pointers to the recipient objects101* within the array, i.e., after the call (including on102* failure), the index fields of the recipient objects103* may no longer correspond to the positions in the104* array. Multiple recipient objects with the same scan105* public key and/or same spend public key can be passed106* if they carry different indices.107* n_recipients: the size of the recipients array.108* outpoint_smallest36: serialized (36-byte) smallest outpoint109* (lexicographically) from the transaction inputs110* keypairs: pointer to an array of pointers to taproot111* keypair inputs (can be NULL if no secret keys112* of taproot inputs are used)113* n_keypairs: the size of the keypairs array.114* seckeys: pointer to an array of pointers to 32-byte115* secret keys of non-taproot inputs (can be NULL116* if no secret keys of non-taproot inputs are117* used)118* n_seckeys: the size of the seckeys array.119*/120SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_sender_create_outputs(121const secp256k1_context *ctx,122secp256k1_xonly_pubkey **generated_outputs,123const secp256k1_silentpayments_recipient **recipients,124size_t n_recipients,125const unsigned char *outpoint_smallest36,126const secp256k1_keypair * const *keypairs,127size_t n_keypairs,128const unsigned char * const *seckeys,129size_t n_seckeys130) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);132/** Opaque data structure that holds a Silent Payments label.133*134* Guaranteed to be 68 bytes in size. Serialized and parsed with135* `secp256k1_silentpayments_recipient_label_serialize` and136* `secp256k1_silentpayments_recipient_label_parse`.137*/138typedef struct secp256k1_silentpayments_label {139unsigned char data[68];140} secp256k1_silentpayments_label;142/** Parse a Silent Payments label.143*144* Returns: 1 when the label could be parsed, 0 otherwise.145* Args: ctx: pointer to a context object146* Out: label: pointer to a label object147* In: in33: pointer to the 33-byte label to be parsed148*/149SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_label_parse(150const secp256k1_context *ctx,151secp256k1_silentpayments_label *label,152const unsigned char *in33153) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);155/** Serialize a Silent Payments label156*157* Returns: 1 always158* Args: ctx: pointer to a context object159* Out: out33: pointer to a 33-byte array to store the serialized label160* In: label: pointer to the label161*/162SECP256K1_API int secp256k1_silentpayments_recipient_label_serialize(163const secp256k1_context *ctx,164unsigned char *out33,165const secp256k1_silentpayments_label *label166) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);168/** Create Silent Payments label tweak and label.169*170* Given a recipient's 32 byte scan key and a label integer m, calculate the171* corresponding label tweak and label:172*173* label_tweak = hash(scan_key || m)174* label = label_tweak * G175*176* Returns: 1 if label tweak and label creation was successful.177* 0 if scan_key32 is invalid or the hash output label_tweak32 is178* not a valid scalar (negligible probability per hash evaluation).179*180* WARNING: Creating a large number of labels may significantly degrade181* scanning performance in certain Silent Payments wallet implementations,182* such as light clients. The scanning function provided in this module,183* which is designed for full nodes, performs consistently even with hundreds184* of thousands of labels. Other implementations may not share this property185* or may be unable to use it due to lacking full transaction data.186*187* To maximize wallet interoperability, it is recommended to create only188* the change label (m = 0) and avoid distributing labeled addresses.189*190* Args: ctx: pointer to a context object191* (not secp256k1_context_static)192* Out: label: pointer to the resulting label193* label_tweak32: pointer to the 32 byte label tweak194* In: scan_key32: pointer to the recipient's 32 byte scan key195* m: integer for the m-th label (0 is used for change outputs)196*/197SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_label_create(198const secp256k1_context *ctx,199secp256k1_silentpayments_label *label,200unsigned char *label_tweak32,201const unsigned char *scan_key32,202uint32_t m203) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);205/** Create Silent Payments labeled spend public key.206*207* Given a recipient's spend public key and a label, calculate the208* corresponding labeled spend public key:209*210* labeled_spend_pubkey = unlabeled_spend_pubkey + label211*212* The result is used by the recipient to create a Silent Payments address,213* consisting of the serialized and concatenated scan public key and214* (labeled) spend public key.215*216* Returns: 1 if labeled spend public key creation was successful.217* 0 if spend pubkey and label sum to zero (negligible probability for218* labels created according to BIP352).219*220* Args: ctx: pointer to a context object221* Out: labeled_spend_pubkey: pointer to the resulting labeled spend public key222* In: unlabeled_spend_pubkey: pointer to the recipient's unlabeled spend public key223* label: pointer to the recipient's label224*/225SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_labeled_spend_pubkey(226const secp256k1_context *ctx,227secp256k1_pubkey *labeled_spend_pubkey,228const secp256k1_pubkey *unlabeled_spend_pubkey,229const secp256k1_silentpayments_label *label230) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);232/** Opaque data structure that holds Silent Payments prevouts summary data.233*234* The exact representation of data inside is implementation defined and not235* guaranteed to be portable between different platforms or versions. It is236* however guaranteed to be 101 bytes in size, and can be safely copied/moved.237* This structure does not contain secret data. It can be created with238* `secp256k1_silentpayments_recipient_prevouts_summary_create`.239*/240typedef struct secp256k1_silentpayments_prevouts_summary {241unsigned char data[101];242} secp256k1_silentpayments_prevouts_summary;244/** Compute Silent Payments prevouts summary from prevout public keys and transaction245* inputs.246*247* Given a list of n public keys A_1...A_n (one for each Silent Payments248* eligible input to spend) and a serialized outpoint_smallest36, create a249* `prevouts_summary` object. This object summarizes the prevout data from the250* transaction inputs needed for scanning.
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.