Skip to content

Commit 5f73bf3

Browse files
committed
Update src/secp256k1 subtree to version with Silent Payments support
This commit contains the secp256k1 draft PR bitcoin#1471 (bitcoin-core/secp256k1#1471) applied on tag v0.4.0 and squashed, without the BIP352 test running suite in Python.
1 parent 4b1196a commit 5f73bf3

File tree

9 files changed

+606
-0
lines changed

9 files changed

+606
-0
lines changed

src/secp256k1/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ if(SECP256K1_ENABLE_MODULE_ELLSWIFT)
7676
add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1)
7777
endif()
7878

79+
option(SECP256K1_ENABLE_MODULE_SILENTPAYMENTS "Enable Silent Payments module." OFF)
80+
if(SECP256K1_ENABLE_MODULE_SILENTPAYMENTS)
81+
add_compile_definitions(ENABLE_MODULE_SILENTPAYMENTS=1)
82+
endif()
83+
7984
option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF)
8085
if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS)
8186
add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1)
@@ -276,6 +281,7 @@ message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOV
276281
message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRAKEYS}")
277282
message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}")
278283
message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}")
284+
message(" Silent Payments ..................... ${SECP256K1_ENABLE_MODULE_SILENTPAYMENTS}")
279285
message("Parameters:")
280286
message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}")
281287
message(" ecmult gen precision bits ........... ${SECP256K1_ECMULT_GEN_PREC_BITS}")

src/secp256k1/Makefile.am

+4
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,7 @@ endif
271271
if ENABLE_MODULE_ELLSWIFT
272272
include src/modules/ellswift/Makefile.am.include
273273
endif
274+
275+
if ENABLE_MODULE_SILENTPAYMENTS
276+
include src/modules/silentpayments/Makefile.am.include
277+
endif

src/secp256k1/configure.ac

+10
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ AC_ARG_ENABLE(module_ellswift,
188188
AS_HELP_STRING([--enable-module-ellswift],[enable ElligatorSwift module [default=yes]]), [],
189189
[SECP_SET_DEFAULT([enable_module_ellswift], [yes], [yes])])
190190

191+
AC_ARG_ENABLE(module_silentpayments,
192+
AS_HELP_STRING([--enable-module-silentpayments],[enable Silent Payments module [default=no]]), [],
193+
[SECP_SET_DEFAULT([enable_module_silentpayments], [no], [yes])])
194+
191195
AC_ARG_ENABLE(external_default_callbacks,
192196
AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [],
193197
[SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])])
@@ -404,6 +408,10 @@ if test x"$enable_module_ellswift" = x"yes"; then
404408
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1"
405409
fi
406410

411+
if test x"$enable_module_silentpayments" = x"yes"; then
412+
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_SILENTPAYMENTS=1"
413+
fi
414+
407415
# Test if extrakeys is set after the schnorrsig module to allow the schnorrsig
408416
# module to set enable_module_extrakeys=yes
409417
if test x"$enable_module_extrakeys" = x"yes"; then
@@ -447,6 +455,7 @@ AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"ye
447455
AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"])
448456
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
449457
AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"])
458+
AM_CONDITIONAL([ENABLE_MODULE_SILENTPAYMENTS], [test x"$enable_module_silentpayments" = x"yes"])
450459
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"])
451460
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"])
452461
AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"])
@@ -469,6 +478,7 @@ echo " module recovery = $enable_module_recovery"
469478
echo " module extrakeys = $enable_module_extrakeys"
470479
echo " module schnorrsig = $enable_module_schnorrsig"
471480
echo " module ellswift = $enable_module_ellswift"
481+
echo " module silentpayments = $enable_module_silentpayments"
472482
echo
473483
echo " asm = $set_asm"
474484
echo " ecmult window size = $set_ecmult_window"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#ifndef SECP256K1_SILENTPAYMENTS_H
2+
#define SECP256K1_SILENTPAYMENTS_H
3+
4+
#include "secp256k1.h"
5+
#include "secp256k1_extrakeys.h"
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
/* This module provides an implementation for the ECC related parts of
12+
* Silent Payments, as specified in BIP352. This particularly involves
13+
* the creation of input tweak data by summing up private or public keys
14+
* and the derivation of a shared secret using Elliptic Curve Diffie-Hellman.
15+
* Combined are either:
16+
* - spender's private keys and receiver's public key (a * B, sender side)
17+
* - spender's public keys and receiver's private key (A * b, receiver side)
18+
* With this result, the necessary key material for ultimately creating/scanning
19+
* or spending Silent Payment outputs can be determined.
20+
*
21+
* Note that this module is _not_ a full implementation of BIP352, as it
22+
* inherently doesn't deal with higher-level concepts like addresses, output
23+
* script types or transactions. The intent is to provide cryptographical
24+
* helpers for low-level calculations that are most error-prone to custom
25+
* implementations (e.g. enforcing the right y-parity for key material, ECDH
26+
* calculation etc.). For any wallet software already using libsecp256k1, this
27+
* API should provide all the functions needed for a Silent Payments
28+
* implementation without the need for any further manual elliptic-curve
29+
* operations.
30+
*/
31+
32+
/** Create Silent Payment tweak data from input private keys.
33+
*
34+
* Given a list of n private keys a_0...a_(n-1) (one for each input to spend)
35+
* and an outpoints_hash, compute the corresponding input private keys tweak data:
36+
*
37+
* a_tweaked = (a_0 + a_1 + ... a_(n-1)) * outpoints_hash
38+
*
39+
* If necessary, the private keys are negated to enforce the right y-parity.
40+
* For that reason, the private keys have to be passed in via two different parameter
41+
* pairs, depending on whether they were used for creating taproot outputs or not.
42+
* The resulting data is needed to create a shared secret for the sender side.
43+
*
44+
* Returns: 1 if shared secret creation was successful. 0 if an error occured.
45+
* Args: ctx: pointer to a context object
46+
* Out: tweak_data32: pointer to the resulting 32-byte tweak data
47+
* In: plain_seckeys: pointer to an array of 32-byte private keys of non-taproot inputs
48+
* (can be NULL if no private keys of non-taproot inputs are used)
49+
* n_plain_seckeys: the number of sender's non-taproot input private keys
50+
* taproot_seckeys: pointer to an array of 32-byte private keys of taproot inputs
51+
* (can be NULL if no private keys of taproot inputs are used)
52+
* n_taproot_seckeys: the number of sender's taproot input private keys
53+
* outpoints_hash32: hash of the sorted serialized outpoints
54+
*/
55+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_private_tweak_data(
56+
const secp256k1_context *ctx,
57+
unsigned char *tweak_data32,
58+
const unsigned char *plain_seckeys,
59+
size_t n_plain_seckeys,
60+
const unsigned char *taproot_seckeys,
61+
size_t n_taproot_seckeys,
62+
const unsigned char *outpoints_hash32
63+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(7);
64+
65+
/** Create Silent Payment shared secret for the sender side.
66+
*
67+
* Given private input tweak data a_tweaked a recipient's scan public key B_scan,
68+
* compute the corresponding shared secret using ECDH:
69+
*
70+
* shared_secret = a_tweaked * B_scan
71+
* (where a_tweaked = (a_0 + a_1 + ... a_(n-1)) * outpoints_hash)
72+
*
73+
* The resulting data is needed as input for creating silent payments outputs
74+
* belonging to the same receiver scan public key.
75+
*
76+
* Returns: 1 if shared secret creation was successful. 0 if an error occured.
77+
* Args: ctx: pointer to a context object
78+
* Out: shared_secret33: pointer to the resulting 33-byte shared secret
79+
* In: tweak_data32: pointer to 32-byte private input tweak data
80+
* receiver_scan_pubkey: pointer to the receiver's scan pubkey
81+
*/
82+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_send_create_shared_secret(
83+
const secp256k1_context *ctx,
84+
unsigned char *shared_secret33,
85+
const unsigned char *tweak_data32,
86+
const secp256k1_pubkey *receiver_scan_pubkey
87+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
88+
89+
/** Create Silent Payment tweak data from input public keys.
90+
*
91+
* Given a list of n public keys A_0...A_(n-1) (one for each input to spend)
92+
* and an outpoints_hash, compute the corresponding input public keys tweak data:
93+
*
94+
* A_tweaked = (A_0 + A_1 + ... A_(n-1)) * outpoints_hash
95+
*
96+
* If necessary, the public keys are negated to enforce the right y-parity.
97+
* For that reason, the public keys have to be passed in via two different parameter
98+
* pairs, depending on whether they were used for creating taproot outputs or not.
99+
* The resulting data is needed to create a shared secret for the receiver's side.
100+
*
101+
* Returns: 1 if tweak data creation was successful. 0 if an error occured.
102+
* Args: ctx: pointer to a context object
103+
* Out: tweak_data33: pointer to the resulting 33-byte tweak data
104+
* In: plain_pubkeys: pointer to an array of non-taproot public keys
105+
* (can be NULL if no non-taproot inputs are used)
106+
* n_plain_pubkeys: the number of non-taproot input public keys
107+
* xonly_pubkeys: pointer to an array of taproot x-only public keys
108+
* (can be NULL if no taproot input public keys are used)
109+
* n_xonly_pubkeys: the number of taproot input public keys
110+
* outpoints_hash32: hash of the sorted serialized outpoints
111+
*/
112+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_public_tweak_data(
113+
const secp256k1_context *ctx,
114+
unsigned char *tweak_data33,
115+
const secp256k1_pubkey *plain_pubkeys,
116+
size_t n_plain_pubkeys,
117+
const secp256k1_xonly_pubkey *xonly_pubkeys,
118+
size_t n_xonly_pubkeys,
119+
const unsigned char *outpoints_hash32
120+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(7);
121+
122+
/** Create Silent Payment shared secret for the receiver side.
123+
*
124+
* Given public input tweak data A_tweaked and a recipient's scan private key
125+
* b_scan, compute the corresponding shared secret using ECDH:
126+
*
127+
* shared_secret = A_tweaked * b_scan
128+
* (where A_tweaked = (A_0 + A_1 + ... A_(n-1)) * outpoints_hash)
129+
*
130+
* The resulting data is needed as input for creating silent payments outputs
131+
* belonging to the same receiver scan public key.
132+
*
133+
* Returns: 1 if shared secret creation was successful. 0 if an error occured.
134+
* Args: ctx: pointer to a context object
135+
* Out: shared_secret33: pointer to the resulting 33-byte shared secret
136+
* In: tweak_data33: pointer to 33-byte public input tweak data
137+
* receiver_scan_seckey: pointer to the receiver's scan private key
138+
*/
139+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_receive_create_shared_secret(
140+
const secp256k1_context *ctx,
141+
unsigned char *shared_secret33,
142+
const unsigned char *tweak_data33,
143+
const unsigned char *receiver_scan_seckey
144+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
145+
146+
/** Create Silent Payment output public key (both for sender and receiver).
147+
*
148+
* Given a shared_secret, a recipient's spend public key B_spend, and an
149+
* output counter k, calculate the corresponding output public key:
150+
*
151+
* P_output = B_spend + sha256(shared_secret || ser_32(k)) * G
152+
*
153+
* Returns: 1 if outputs creation was successful. 0 if an error occured.
154+
* Args: ctx: pointer to a context object
155+
* Out: output_xonly_pubkey: pointer to the resulting output x-only pubkey
156+
* In: shared_secret33: shared secret, derived from either sender's
157+
* or receiver's perspective with routines from above
158+
* receiver_spend_pubkey: pointer to the receiver's spend pubkey
159+
* k: output counter (usually set to 0, should be increased for
160+
* every additional output to the same recipient)
161+
* label_tweak32: an optional 32-byte label tweak
162+
* (not supported yet, must be set to NULL right now)
163+
*/
164+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_output_pubkey(
165+
const secp256k1_context *ctx,
166+
secp256k1_xonly_pubkey *output_xonly_pubkey,
167+
const unsigned char *shared_secret33,
168+
const secp256k1_pubkey *receiver_spend_pubkey,
169+
unsigned int k,
170+
const unsigned char *label_tweak32
171+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
172+
173+
/** Create Silent Payment output private key (for spending receiver's funds).
174+
*
175+
* Given a shared_secret, a recipient's spend private key b_spend, and an
176+
* output counter k, calculate the corresponding output private key d:
177+
*
178+
* d = (b_spend + sha256(shared_secret || ser_32(k))) mod n
179+
*
180+
* Returns: 1 if private key creation was successful. 0 if an error occured.
181+
* Args: ctx: pointer to a context object
182+
* Out: output_seckey: pointer to the resulting spending private key
183+
* In: shared_secret33: shared secret, derived from either sender's
184+
* or receiver's perspective with routines from above
185+
* receiver_spend_seckey: pointer to the receiver's spend private key
186+
* k: output counter (usually set to 0, should be increased for
187+
* every additional output to the same recipient)
188+
* label_tweak32: an optional 32-byte label tweak
189+
* (not supported yet, must be set to NULL right now)
190+
*/
191+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_output_seckey(
192+
const secp256k1_context *ctx,
193+
unsigned char *output_seckey,
194+
const unsigned char *shared_secret33,
195+
const unsigned char *receiver_spend_seckey,
196+
unsigned int k,
197+
const unsigned char *label_tweak32
198+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
199+
200+
#ifdef __cplusplus
201+
}
202+
#endif
203+
204+
#endif /* SECP256K1_SILENTPAYMENTS_H */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include_HEADERS += include/secp256k1_silentpayments.h
2+
noinst_HEADERS += src/modules/silentpayments/main_impl.h

0 commit comments

Comments
 (0)