Skip to content

Commit c5db922

Browse files
committed
add secp256k1_silentpayments_sender_create_outputs_with_proof
- add new API which returns DLEQ proofs along with outputs for recipients - the existing API secp256k1_silentpayments_sender_create_outputs simply calls secp256k1_silentpayments_sender_create_outputs_with_proof internally.
1 parent fb1fd4e commit c5db922

File tree

2 files changed

+79
-7
lines changed

2 files changed

+79
-7
lines changed

include/secp256k1_silentpayments.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,36 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_sender_c
142142
size_t n_plain_seckeys
143143
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
144144

145+
/** Create Silent Payment outputs and associated DLEQ proof(s) for recipient(s).
146+
*
147+
* Similar to secp256k1_silentpayments_sender_create_outputs,
148+
* but also returns information about associated DLEQ proof.
149+
*
150+
* Returns: 1 if creation of outputs was successful. 0 if an error occurred.
151+
* Args: ctx: pointer to a context object
152+
* Out: generated_outputs: pointer to an array of pointers to xonly pubkeys,
153+
* one per recipient.
154+
* The order of outputs here matches the original
155+
* ordering of the recipients array.
156+
* dleq_data: pointer to an array of pointers to secp256k1_silentpayments_dleq_data,
157+
* one per unique recipient.
158+
* n_dleq_size: number of DLEQ proofs generated (equivalent to number of unique recipients)
159+
* In: See input parameters in secp256k1_silentpayments_sender_create_outputs
160+
*/
161+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_sender_create_outputs_with_proof(
162+
const secp256k1_context *ctx,
163+
secp256k1_xonly_pubkey **generated_outputs,
164+
secp256k1_silentpayments_dleq_data **dleq_data,
165+
size_t *n_dleq_size,
166+
const secp256k1_silentpayments_recipient **recipients,
167+
size_t n_recipients,
168+
const unsigned char *outpoint_smallest36,
169+
const secp256k1_keypair * const *taproot_seckeys,
170+
size_t n_taproot_seckeys,
171+
const unsigned char * const *plain_seckeys,
172+
size_t n_plain_seckeys
173+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(7);
174+
145175
/** Create Silent Payment label tweak and label.
146176
*
147177
* Given a recipient's 32 byte scan key and a label integer m, calculate the

src/modules/silentpayments/main_impl.h

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,11 @@ static int secp256k1_silentpayments_create_output_pubkey(const secp256k1_context
211211
return 1;
212212
}
213213

214-
int secp256k1_silentpayments_sender_create_outputs(
214+
int secp256k1_silentpayments_sender_create_outputs_with_proof(
215215
const secp256k1_context *ctx,
216216
secp256k1_xonly_pubkey **generated_outputs,
217+
secp256k1_silentpayments_dleq_data **dleq_data,
218+
size_t *n_dleq_size,
217219
const secp256k1_silentpayments_recipient **recipients,
218220
size_t n_recipients,
219221
const unsigned char *outpoint_smallest36,
@@ -226,9 +228,13 @@ int secp256k1_silentpayments_sender_create_outputs(
226228
secp256k1_scalar seckey_sum_scalar, addend, input_hash_scalar;
227229
secp256k1_ge prevouts_pubkey_sum_ge;
228230
secp256k1_gej prevouts_pubkey_sum_gej;
229-
unsigned char shared_secret[33];
231+
secp256k1_ge shared_secret;
232+
unsigned char shared_secret33[33];
233+
unsigned char proof64[64];
230234
secp256k1_pubkey current_scan_pubkey;
231-
int ret, sum_is_zero;
235+
int ret = 0, sum_is_zero;
236+
int j = 0;
237+
size_t len;
232238

233239
/* Sanity check inputs. */
234240
VERIFY_CHECK(ctx != NULL);
@@ -328,21 +334,57 @@ int secp256k1_silentpayments_sender_create_outputs(
328334
secp256k1_memclear_explicit(&shared_secret, sizeof(shared_secret));
329335
return 0;
330336
}
331-
secp256k1_silentpayments_create_shared_secret(ctx, shared_secret, &pk, &seckey_sum_scalar);
337+
/* Compute shared_secret = tweaked_secret_component * Public_component */
338+
secp256k1_silentpayments_create_shared_secret_with_proof(ctx, proof64, &shared_secret, &pk, &seckey_sum_scalar);
339+
if (dleq_data != NULL) {
340+
secp256k1_pubkey pubkey;
341+
size_t pklen = 33;
342+
secp256k1_pubkey_save(&pubkey, &shared_secret);
343+
secp256k1_ec_pubkey_serialize(ctx, dleq_data[j]->shared_secret, &pklen, &pubkey, SECP256K1_EC_COMPRESSED);
344+
memcpy(dleq_data[j]->proof, proof64, 64);
345+
dleq_data[j]->index = recipients[i]->index;
346+
}
347+
/* This can only fail if the shared secret is the point at infinity, which should be
348+
* impossible at this point, considering we have already validated the public key and
349+
* the secret key being used
350+
*/
351+
ret = secp256k1_eckey_pubkey_serialize(&shared_secret, shared_secret33, &len, 1);
352+
VERIFY_CHECK(ret && len == 33);
332353
k = 0;
354+
j++;
333355
}
334-
if (!secp256k1_silentpayments_create_output_pubkey(ctx, generated_outputs[recipients[i]->index], shared_secret, &recipients[i]->spend_pubkey, k)) {
356+
if (!secp256k1_silentpayments_create_output_pubkey(ctx, generated_outputs[recipients[i]->index], shared_secret33, &recipients[i]->spend_pubkey, k)) {
335357
secp256k1_scalar_clear(&seckey_sum_scalar);
336358
secp256k1_memclear_explicit(&shared_secret, sizeof(shared_secret));
337359
return 0;
338360
}
339361
VERIFY_CHECK(k < SIZE_MAX);
362+
ret &= secp256k1_silentpayments_create_output_pubkey(ctx, generated_outputs[recipients[i]->index], shared_secret33, &recipients[i]->spend_pubkey, k);
340363
k++;
341364
current_scan_pubkey = recipients[i]->scan_pubkey;
342365
}
366+
*n_dleq_size = j;
343367
secp256k1_scalar_clear(&seckey_sum_scalar);
344-
secp256k1_memclear_explicit(&shared_secret, sizeof(shared_secret));
345-
return 1;
368+
secp256k1_ge_clear(&shared_secret);
369+
secp256k1_memclear_explicit(&shared_secret33, sizeof(shared_secret33));
370+
return ret;
371+
}
372+
373+
int secp256k1_silentpayments_sender_create_outputs(
374+
375+
376+
const secp256k1_context *ctx,
377+
secp256k1_xonly_pubkey **generated_outputs,
378+
const secp256k1_silentpayments_recipient **recipients,
379+
size_t n_recipients,
380+
const unsigned char *outpoint_smallest36,
381+
const secp256k1_keypair * const *taproot_seckeys,
382+
size_t n_taproot_seckeys,
383+
const unsigned char * const *plain_seckeys,
384+
size_t n_plain_seckeys
385+
) {
386+
size_t n_dleq_size;
387+
return secp256k1_silentpayments_sender_create_outputs_with_proof(ctx, generated_outputs, NULL, &n_dleq_size, recipients, n_recipients, outpoint_smallest36, taproot_seckeys, n_taproot_seckeys, plain_seckeys, n_plain_seckeys);
346388
}
347389

348390
/** Set hash state to the BIP340 tagged hash midstate for "BIP0352/Label". */

0 commit comments

Comments
 (0)