Bitcoin Core 31.99.0
P2P Digital Currency
silentpayments.c
Go to the documentation of this file.
1/*************************************************************************
2 * To the extent possible under law, the author(s) have dedicated all *
3 * copyright and related and neighboring rights to the software in this *
4 * file to the public domain worldwide. This software is distributed *
5 * without any warranty. For the CC0 Public Domain Dedication, see *
6 * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 *
7 *************************************************************************/
8
9#include <assert.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include <secp256k1_extrakeys.h>
16
17#include "examples_util.h"
18
19#define N_INPUTS 2
20#define N_OUTPUTS 3
21
22/* Static data for Bob and Carol's Silent Payments addresses */
23static unsigned char smallest_outpoint[36] = {
24 0x16, 0x9e, 0x1e, 0x83, 0xe9, 0x30, 0x85, 0x33, 0x91,
25 0xbc, 0x6f, 0x35, 0xf6, 0x05, 0xc6, 0x75, 0x4c, 0xfe,
26 0xad, 0x57, 0xcf, 0x83, 0x87, 0x63, 0x9d, 0x3b, 0x40,
27 0x96, 0xc5, 0x4f, 0x18, 0xf4, 0x00, 0x00, 0x00, 0x00
28};
29static unsigned char bob_scan_key[32] = {
30 0xa8, 0x90, 0x54, 0xc9, 0x5b, 0xe3, 0xc3, 0x01,
31 0x56, 0x65, 0x74, 0xf2, 0xaa, 0x93, 0xad, 0xe0,
32 0x51, 0x85, 0x09, 0x03, 0xa6, 0x9c, 0xbd, 0xd1,
33 0xd4, 0x7e, 0xae, 0x26, 0x3d, 0x7b, 0xc0, 0x31
34};
35static unsigned char bob_spend_key[32] = {
36 0x9d, 0x6a, 0xd8, 0x55, 0xce, 0x34, 0x17, 0xef,
37 0x84, 0xe8, 0x36, 0x89, 0x2e, 0x5a, 0x56, 0x39,
38 0x2b, 0xfb, 0xa0, 0x5f, 0xa5, 0xd9, 0x7c, 0xce,
39 0xa3, 0x0e, 0x26, 0x6f, 0x54, 0x0e, 0x08, 0xb3
40};
41static unsigned char bob_scan_and_spend_pubkeys[2][33] = {
42 {
43 0x02, 0x15, 0x40, 0xae, 0xa8, 0x97, 0x54, 0x7a,
44 0xd4, 0x39, 0xb4, 0xe0, 0xf6, 0x09, 0xe5, 0xf0,
45 0xfa, 0x63, 0xde, 0x89, 0xab, 0x11, 0xed, 0xe3,
46 0x1e, 0x8c, 0xde, 0x4b, 0xe2, 0x19, 0x42, 0x5f, 0x23
47 },
48 {
49 0x02, 0x5c, 0xc9, 0x85, 0x6d, 0x6f, 0x83, 0x75,
50 0x35, 0x0e, 0x12, 0x39, 0x78, 0xda, 0xac, 0x20,
51 0x0c, 0x26, 0x0c, 0xb5, 0xb5, 0xae, 0x83, 0x10,
52 0x6c, 0xab, 0x90, 0x48, 0x4d, 0xcd, 0x8f, 0xcf, 0x36
53 }
54};
55static unsigned char carol_scan_key[32] = {
56 0x04, 0xb2, 0xa4, 0x11, 0x63, 0x5c, 0x09, 0x77,
57 0x59, 0xaa, 0xcd, 0x0f, 0x00, 0x5a, 0x4c, 0x82,
58 0xc8, 0xc9, 0x28, 0x62, 0xc6, 0xfc, 0x28, 0x4b,
59 0x80, 0xb8, 0xef, 0xeb, 0xc2, 0x0c, 0x3d, 0x17
60};
61static unsigned char carol_address[2][33] = {
62 {
63 0x03, 0xbb, 0xc6, 0x3f, 0x12, 0x74, 0x5d, 0x3b,
64 0x9e, 0x9d, 0x24, 0xc6, 0xcd, 0x7a, 0x1e, 0xfe,
65 0xba, 0xd0, 0xa7, 0xf4, 0x69, 0x23, 0x2f, 0xbe,
66 0xcf, 0x31, 0xfb, 0xa7, 0xb4, 0xf7, 0xdd, 0xed, 0xa8
67 },
68 {
69 0x03, 0x81, 0xeb, 0x9a, 0x9a, 0x9e, 0xc7, 0x39,
70 0xd5, 0x27, 0xc1, 0x63, 0x1b, 0x31, 0xb4, 0x21,
71 0x56, 0x6f, 0x5c, 0x2a, 0x47, 0xb4, 0xab, 0x5b,
72 0x1f, 0x6a, 0x68, 0x6d, 0xfb, 0x68, 0xea, 0xb7, 0x16
73 }
74};
75
92 unsigned char label[33];
93 unsigned char label_tweak[32];
94};
95
99};
100
101const unsigned char* label_lookup(
102 const unsigned char* label33,
103 const void* cache_ptr
104) {
105 const struct labels_cache* cache = (const struct labels_cache*)cache_ptr;
106 size_t i;
107 for (i = 0; i < cache->entries_used; i++) {
108 if (memcmp(cache->entries[i].label, label33, 33) == 0) {
109 return cache->entries[i].label_tweak;
110 }
111 }
112 return NULL;
113}
114
115int main(void) {
116 unsigned char randomize[32];
117 unsigned char serialized_xonly[32];
119 const secp256k1_xonly_pubkey *tx_input_ptrs[N_INPUTS];
121 secp256k1_xonly_pubkey *tx_output_ptrs[N_OUTPUTS];
125 secp256k1_pubkey unlabeled_spend_pubkey;
126 struct labels_cache bob_labels_cache;
127 unsigned char bob_address[2][33];
128 int ret;
129 size_t i;
130 uint32_t n_found_outputs;
131
132 /* Before we can call actual API functions, we need to create a "context" */
134 if (!fill_random(randomize, sizeof(randomize))) {
135 printf("Failed to generate randomness\n");
136 return EXIT_FAILURE;
137 }
138 /* Randomizing the context is recommended to protect against side-channel
139 * leakage. See `secp256k1_context_randomize` in secp256k1.h for more
140 * information about it. This should never fail. */
141 ret = secp256k1_context_randomize(ctx, randomize);
142 assert(ret);
143
144 /* Set up the pointer arrays. These will be used for sending and scanning. */
145 for (i = 0; i < N_INPUTS; i++) {
146 tx_input_ptrs[i] = &tx_inputs[i];
147 }
148 for (i = 0; i < N_OUTPUTS; i++) {
149 tx_output_ptrs[i] = &tx_outputs[i];
150 found_output_ptrs[i] = &found_outputs[i];
151 }
152
153 /*** Create a labeled Silent Payments address (Bob) ***/
154 {
155 size_t len = 33;
157 secp256k1_pubkey labeled_spend_pubkey;
158 /* Per BIP-352, the label integer value m = 0 is reserved for the receiver's own
159 * change, so only values m >= 1 must be used for publishing addresses. */
160 uint32_t m = 1;
161
162 /* Load Bob's spend public key */
164 &unlabeled_spend_pubkey,
166 33
167 );
168 assert(ret);
169 /* Create a (label_tweak, label) pair and add them to the labels cache.
170 *
171 * Bob MUST keep track of all of the labels he has used by adding them
172 * to the labels cache. Otherwise, he will not find outputs sent to his
173 * labeled addresses when scanning. */
175 &label,
176 bob_labels_cache.entries[0].label_tweak,
178 m
179 );
180 if (!ret) {
181 printf("Something went wrong, event with negligible probability happened.\n");
182 return EXIT_FAILURE;
183 }
184 ret = secp256k1_silentpayments_recipient_label_serialize(ctx, bob_labels_cache.entries[0].label, &label);
185 assert(ret);
186 bob_labels_cache.entries_used = 1;
187 /* Now that the labels cache has been updated, Bob creates his labeled
188 * Silent Payments address and publishes it.
189 */
190 ret = secp256k1_silentpayments_recipient_create_labeled_spend_pubkey(ctx, &labeled_spend_pubkey, &unlabeled_spend_pubkey, &label);
191 if (!ret) {
192 printf("Something went wrong, event with negligible probability happened.\n");
193 return EXIT_FAILURE;
194 }
195 memcpy(bob_address[0], bob_scan_and_spend_pubkeys[0], 33);
197 bob_address[1],
198 &len,
199 &labeled_spend_pubkey,
201 );
202 assert(ret);
203 }
204 /*** Sending (Alice) ***/
205 {
206 secp256k1_keypair sender_keypairs[N_INPUTS];
207 const secp256k1_keypair *sender_keypair_ptrs[N_INPUTS];
209 const secp256k1_silentpayments_recipient *recipient_ptrs[N_OUTPUTS];
210 /* 2D array for holding multiple public key pairs. The second index, i.e., [2],
211 * is to represent the spend and scan public keys. */
212 unsigned char (*sp_addresses[N_OUTPUTS])[2][33];
213 unsigned char seckey[32];
214
215 /*** Generate secret keys for the sender ***
216 *
217 * In this example, only taproot inputs are used but the function can be
218 * called with a mix of taproot seckeys and plain seckeys. Taproot
219 * seckeys are passed as keypairs to allow the sending function to check
220 * if the secret keys need to be negated without needing to do an
221 * expensive pubkey generation. This is not needed for plain seckeys
222 * since there is no need for negation.
223 *
224 * The public key from each input keypair is saved in the `tx_inputs`
225 * array. This array will be used later in the example to represent the
226 * public keys the recipient will extract from the transaction inputs.
227 *
228 * If the secret key is zero or out of range (bigger than secp256k1's
229 * order), fail. Note that the probability of this happening is
230 * negligible. */
231 for (i = 0; i < N_INPUTS; i++) {
232 if (!fill_random(seckey, sizeof(seckey))) {
233 printf("Failed to generate randomness\n");
234 return EXIT_FAILURE;
235 }
236 /* Try to create a keypair with a valid context, it should only fail
237 * if the secret key is zero or out of range. */
238 if (secp256k1_keypair_create(ctx, &sender_keypairs[i], seckey)) {
239 sender_keypair_ptrs[i] = &sender_keypairs[i];
241 ctx,
242 &tx_inputs[i],
243 NULL,
244 &sender_keypairs[i]
245 );
246 assert(ret);
247 } else {
248 printf("Failed to create keypair\n");
249 return EXIT_FAILURE;
250 }
251 }
252 /*** Create the recipient objects ***/
253
254 /* Alice is sending to Bob and Carol in this transaction:
255 *
256 * 1. One output to Bob's labeled address
257 * 2. Two outputs for Carol
258 *
259 * To create multiple outputs for Carol, Alice simply passes Carol's
260 * Silent Payments address multiple times.
261 */
262 sp_addresses[0] = &carol_address;
263 sp_addresses[1] = &bob_address;
264 sp_addresses[2] = &carol_address;
265 for (i = 0; i < N_OUTPUTS; i++) {
267 &recipients[i].scan_pubkey,
268 (*(sp_addresses[i]))[0],
269 33
270 );
272 &recipients[i].spend_pubkey,
273 (*(sp_addresses[i]))[1],
274 33
275 );
276 if (!ret) {
277 printf("Something went wrong, this is not a valid Silent Payments address.\n");
278 return EXIT_FAILURE;
279 }
280
281 /* Alice creates the recipient objects and adds the index of the
282 * original ordering (the ordering of the `sp_addresses` array) to
283 * each object. This index is used to return the generated outputs
284 * in the original ordering so that Alice can match up the generated
285 * outputs with the correct amounts.
286 */
287 recipients[i].index = i;
288 recipient_ptrs[i] = &recipients[i];
289 }
291 tx_output_ptrs,
292 recipient_ptrs, N_OUTPUTS,
294 sender_keypair_ptrs, N_INPUTS,
295 NULL, 0
296 );
297 if (!ret) {
298 printf("Something went wrong, a recipient provided an invalid address.\n");
299 return EXIT_FAILURE;
300 }
301 printf("Alice created the following outputs for Bob and Carol:\n");
302 for (i = 0; i < N_OUTPUTS; i++) {
303 printf(" ");
305 serialized_xonly,
306 &tx_outputs[i]
307 );
308 assert(ret);
309 print_hex(serialized_xonly, sizeof(serialized_xonly));
310 }
311 /* It's best practice to try to clear secrets from memory after using
312 * them. This is done because some bugs can allow an attacker to leak
313 * memory, for example through "out of bounds" array access (see
314 * Heartbleed), or the OS swapping them to disk. Hence, we overwrite the
315 * secret key buffer with zeros.
316 *
317 * Here we are preventing these writes from being optimized out, as any
318 * good compiler will remove any writes that aren't used. */
319 secure_erase(seckey, sizeof(seckey));
320 for (i = 0; i < N_INPUTS; i++) {
321 secure_erase(&sender_keypairs[i], sizeof(sender_keypairs[i]));
322 }
323 }
324
325 /*** Receiving ***/
326 {
327 {
328 /*** Scanning as a full node (Bob) ***
329 *
330 * Since Bob has access to the full transaction, scanning is simple:
331 *
332 * 1. Collect the relevant prevouts from the transaction and call
333 * `secp256k1_silentpayments_recipient_prevouts_summary_create`
334 * 2. Call `secp256k1_silentpayments_recipient_scan_outputs`
335 */
337 &prevouts_summary,
339 tx_input_ptrs, N_INPUTS,
340 NULL, 0
341 );
342 if (!ret) {
343 /* We need to always check that the prevouts data object is valid
344 * before proceeding.
345 */
346 printf("This transaction is not valid for Silent Payments, skipping.\n");
347 return EXIT_SUCCESS;
348 }
349
350 /* Scan the transaction */
351 n_found_outputs = 0;
353 found_output_ptrs, &n_found_outputs,
354 (const secp256k1_xonly_pubkey**)tx_output_ptrs, N_OUTPUTS,
356 &prevouts_summary,
357 &unlabeled_spend_pubkey,
358 label_lookup, &bob_labels_cache /* NULL, NULL for no labels */
359 );
360 if (!ret) {
361 printf("This transaction is not valid for Silent Payments, skipping.\n");
362 return EXIT_SUCCESS;
363 }
364 if (n_found_outputs > 0) {
366 secp256k1_xonly_pubkey xonly_output;
367 unsigned char full_seckey[32];
368
369 printf("\n");
370 printf("Bob found the following outputs: \n");
371 for (i = 0; i < n_found_outputs; i++) {
372 printf(" ");
374 serialized_xonly,
375 &found_outputs[i].output
376 );
377 assert(ret);
378 print_hex(serialized_xonly, sizeof(serialized_xonly));
379
380 /* Verify that this output is spendable by Bob by reconstructing the full
381 * secret key for the xonly output.
382 *
383 * This is done by adding the tweak from the transaction to Bob's spend key.
384 * If the output was sent to a labeled address, the label tweak has already
385 * been added to the tweak in `secp256k1_silentpayments_found_output`.
386 *
387 * To verify that we are able to sign for this output, it is sufficient to
388 * check that the public key generated from `full_seckey` matches the output
389 * in the transaction. For a full example on signing for a taproot ouput,
390 * see `examples/schnorr.c`.
391 */
392 memcpy(&full_seckey, &bob_spend_key, 32);
393 ret = secp256k1_ec_seckey_tweak_add(ctx, full_seckey, found_outputs[i].tweak);
394 ret &= secp256k1_keypair_create(ctx, &kp, full_seckey);
396 ctx,
397 &xonly_output,
398 NULL,
399 &kp
400 );
401 /* We assert here because the only way the seckey_tweak_add operation can fail
402 * is if the tweak is the negation of Bob's spend key.
403 *
404 * We also assert that the generated public key matches the transaction output,
405 * as it should be impossible for a mismatch at this point considering the
406 * scanning function completed without errors and indicated found outputs.
407 */
408 assert(ret);
409 assert(secp256k1_xonly_pubkey_cmp(ctx, &xonly_output, &found_outputs[i].output) == 0);
410 secure_erase(full_seckey, sizeof(full_seckey));
411 }
412 } else {
413 printf("Bob did not find any outputs in this transaction.\n");
414 }
415 }
416 {
417 /*** Scanning as a full node (Carol) ***/
418 /* TODO: switch this part to light client scanning once it is supported */
419
420 /* Load Carol's spend public key. */
422 &unlabeled_spend_pubkey,
423 carol_address[1],
424 33
425 );
426 assert(ret);
427
428 n_found_outputs = 0;
430 found_output_ptrs, &n_found_outputs,
431 (const secp256k1_xonly_pubkey**)tx_output_ptrs, N_OUTPUTS,
433 &prevouts_summary,
434 &unlabeled_spend_pubkey,
435 NULL, NULL /* NULL, NULL for no labels */
436 );
437 if (!ret) {
438 printf("This transaction is not valid for Silent Payments, skipping.\n");
439 return EXIT_SUCCESS;
440 }
441 if (n_found_outputs > 0) {
442 /* Carol would spend these outputs the same as Bob, by tweaking her
443 * spend key with the tweak corresponding to the found output. See above
444 * for an example for Bob's outputs. */
445 printf("\n");
446 printf("Carol found the following outputs: \n");
447 for (i = 0; i < n_found_outputs; i++) {
448 printf(" ");
450 serialized_xonly,
451 &found_outputs[i].output
452 );
453 assert(ret);
454 print_hex(serialized_xonly, sizeof(serialized_xonly));
455 }
456 } else {
457 printf("Carol did not find any outputs in this transaction.\n");
458 }
459 }
460 }
461
462 /* This will clear everything from the context and free the memory */
464 return EXIT_SUCCESS;
465}
int ret
return EXIT_SUCCESS
static int fill_random(unsigned char *data, size_t size)
Definition: examples_util.h:43
static void secure_erase(void *ptr, size_t len)
Definition: examples_util.h:86
static void print_hex(unsigned char *data, size_t size)
Definition: examples_util.h:72
static int tweak(const secp256k1_context *ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache)
Definition: musig.c:64
void printf(FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1096
SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx) SECP256K1_ARG_NONNULL(1)
Destroy a secp256k1 context object (created in dynamically allocated memory).
Definition: secp256k1.c:190
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(secp256k1_context *ctx, const unsigned char *seed32) SECP256K1_ARG_NONNULL(1)
Randomizes the context to provide enhanced protection against side-channel leakage.
Definition: secp256k1.c:780
SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Serialize a pubkey object into a serialized byte sequence.
Definition: secp256k1.c:287
SECP256K1_API secp256k1_context * secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT
Create a secp256k1 context object (in dynamically allocated memory).
Definition: secp256k1.c:144
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a variable-length public key into the pubkey object.
Definition: secp256k1.c:269
#define SECP256K1_CONTEXT_NONE
Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size,...
Definition: secp256k1.h:215
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:225
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add(const secp256k1_context *ctx, unsigned char *seckey, const unsigned char *tweak32) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Tweak a secret key by adding tweak to it.
Definition: secp256k1.c:697
SECP256K1_API int secp256k1_xonly_pubkey_cmp(const secp256k1_context *ctx, const secp256k1_xonly_pubkey *pk1, const secp256k1_xonly_pubkey *pk2) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Compare two x-only public keys using lexicographic order.
Definition: main_impl.h:66
SECP256K1_API int secp256k1_xonly_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Serialize an xonly_pubkey object into a 32-byte sequence.
Definition: main_impl.h:51
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(const secp256k1_context *ctx, secp256k1_keypair *keypair, const unsigned char *seckey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Compute the keypair for a valid secret key.
Definition: main_impl.h:203
SECP256K1_API int secp256k1_keypair_xonly_pub(const secp256k1_context *ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4)
Get the x-only public key from a keypair.
Definition: main_impl.h:241
SECP256K1_API int secp256k1_silentpayments_recipient_label_serialize(const secp256k1_context *ctx, unsigned char *out33, const secp256k1_silentpayments_label *label) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Serialize a Silent Payments label.
Definition: main_impl.h:378
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_prevouts_summary_create(const secp256k1_context *ctx, secp256k1_silentpayments_prevouts_summary *prevouts_summary, const unsigned char *outpoint_smallest36, const secp256k1_xonly_pubkey *const *xonly_pubkeys, size_t n_xonly_pubkeys, const secp256k1_pubkey *const *pubkeys, size_t n_pubkeys) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Compute Silent Payments prevouts summary from prevout public keys and transaction inputs.
Definition: main_impl.h:488
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_sender_create_outputs(const secp256k1_context *ctx, secp256k1_xonly_pubkey **generated_outputs, const secp256k1_silentpayments_recipient **recipients, size_t n_recipients, const unsigned char *outpoint_smallest36, const secp256k1_keypair *const *keypairs, size_t n_keypairs, const unsigned char *const *seckeys, size_t n_seckeys) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5)
Create Silent Payments outputs for recipient(s).
Definition: main_impl.h:187
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_labeled_spend_pubkey(const secp256k1_context *ctx, secp256k1_pubkey *labeled_spend_pubkey, const secp256k1_pubkey *unlabeled_spend_pubkey, const secp256k1_silentpayments_label *label) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Create Silent Payments labeled spend public key.
Definition: main_impl.h:430
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_scan_outputs(const secp256k1_context *ctx, secp256k1_silentpayments_found_output **found_outputs, uint32_t *n_found_outputs, const secp256k1_xonly_pubkey *const *tx_outputs, size_t n_tx_outputs, const unsigned char *scan_key32, const secp256k1_silentpayments_prevouts_summary *prevouts_summary, const secp256k1_pubkey *unlabeled_spend_pubkey, secp256k1_silentpayments_label_lookup label_lookup, const void *label_context) 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)
Scan for Silent Payments transaction outputs.
Definition: main_impl.h:603
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_label_create(const secp256k1_context *ctx, secp256k1_silentpayments_label *label, unsigned char *label_tweak32, const unsigned char *scan_key32, uint32_t m) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Create Silent Payments label tweak and label.
Definition: main_impl.h:393
static unsigned char bob_spend_key[32]
static unsigned char bob_scan_key[32]
static unsigned char smallest_outpoint[36]
const unsigned char * label_lookup(const unsigned char *label33, const void *cache_ptr)
int main(void)
static unsigned char bob_scan_and_spend_pubkeys[2][33]
static unsigned char carol_scan_key[32]
#define N_OUTPUTS
static unsigned char carol_address[2][33]
#define N_INPUTS
Labels.
unsigned char label_tweak[32]
unsigned char label[33]
struct label_cache_entry entries[5]
size_t entries_used
Opaque data structure that holds a keypair consisting of a secret and a public key.
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:62
Opaque data structure that holds a Silent Payments label.
Opaque data structure that holds Silent Payments prevouts summary data.
The data from a single recipient address.
Opaque data structure that holds a parsed and valid "x-only" public key.
assert(!tx.IsCoinBase())