Skip to content

Commit 3710736

Browse files
committed
musig: allow ordinary, non-xonly tweaking
1 parent c519b46 commit 3710736

File tree

4 files changed

+169
-90
lines changed

4 files changed

+169
-90
lines changed

include/secp256k1_musig.h

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,59 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get(
241241
secp256k1_musig_keyagg_cache *keyagg_cache
242242
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
243243

244-
/** Tweak an x-only public key in a given keyagg_cache by adding
245-
* the generator multiplied with `tweak32` to it.
244+
/** Apply ordinary "EC" tweaking to a public key in a given keyagg_cache by
245+
* adding the generator multiplied with `tweak32` to it. This is useful for
246+
* deriving child keys from an aggregate public key via BIP32.
247+
*
248+
* The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after
249+
* the following pseudocode buf and buf2 have identical contents (absent
250+
* earlier failures).
251+
*
252+
* secp256k1_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...)
253+
* secp256k1_musig_pubkey_get(..., agg_pk, keyagg_cache)
254+
* secp256k1_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache)
255+
* secp256k1_ec_pubkey_serialize(..., buf, output_pk)
256+
* secp256k1_ec_pubkey_tweak_add(..., agg_pk, tweak32)
257+
* secp256k1_ec_pubkey_serialize(..., buf2, agg_pk)
258+
*
259+
* This function is required if you want to _sign_ for a tweaked aggregate key.
260+
* On the other hand, if you are only computing a public key, but not intending
261+
* to create a signature for it, you can just use
262+
* `secp256k1_ec_pubkey_tweak_add`.
263+
*
264+
* Returns: 0 if the arguments are invalid or the resulting public key would be
265+
* invalid (only when the tweak is the negation of the corresponding
266+
* secret key). 1 otherwise.
267+
* Args: ctx: pointer to a context object initialized for verification
268+
* Out: output_pubkey: pointer to a public key to store the result. Will be set
269+
* to an invalid value if this function returns 0. If you
270+
* do not need it, this arg can be NULL.
271+
* In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by
272+
* `musig_pubkey_agg`
273+
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid
274+
* according to `secp256k1_ec_seckey_verify`, this function
275+
* returns 0. For uniformly random 32-byte arrays the
276+
* chance of being invalid is negligible (around 1 in
277+
* 2^128).
278+
*/
279+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_ec_tweak_add(
280+
const secp256k1_context* ctx,
281+
secp256k1_pubkey *output_pubkey,
282+
secp256k1_musig_keyagg_cache *keyagg_cache,
283+
const unsigned char *tweak32
284+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
285+
286+
/** Apply x-only tweaking to a public key in a given keyagg_cache by adding the
287+
* generator multiplied with `tweak32` to it. This is useful for creating
288+
* Taproot outputs.
246289
*
247290
* The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in
248291
* the following pseudocode xonly_pubkey_tweak_add_check (absent earlier
249292
* failures) returns 1.
250293
*
251294
* secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...)
252-
* secp256k1_musig_pubkey_tweak_add(..., output_pubkey, tweak32, keyagg_cache)
253-
* secp256k1_xonly_pubkey_serialize(..., buf, output_pubkey)
295+
* secp256k1_musig_pubkey_xonly_tweak_add(..., output_pk, tweak32, keyagg_cache)
296+
* secp256k1_xonly_pubkey_serialize(..., buf, output_pk)
254297
* secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32)
255298
*
256299
* This function is required if you want to _sign_ for a tweaked aggregate key.
@@ -273,7 +316,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get(
273316
* chance of being invalid is negligible (around 1 in
274317
* 2^128).
275318
*/
276-
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_tweak_add(
319+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_tweak_add(
277320
const secp256k1_context* ctx,
278321
secp256k1_pubkey *output_pubkey,
279322
secp256k1_musig_keyagg_cache *keyagg_cache,

src/modules/musig/keyagg_impl.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ int secp256k1_musig_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *a
258258
return 1;
259259
}
260260

261-
int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) {
261+
static int secp256k1_musig_pubkey_tweak_add_internal(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32, int xonly) {
262262
secp256k1_keyagg_cache_internal cache_i;
263263
int overflow = 0;
264264
secp256k1_scalar tweak;
@@ -277,7 +277,7 @@ int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pub
277277
if (overflow) {
278278
return 0;
279279
}
280-
if (secp256k1_extrakeys_ge_even_y(&cache_i.pk)) {
280+
if (xonly && secp256k1_extrakeys_ge_even_y(&cache_i.pk)) {
281281
cache_i.internal_key_parity ^= 1;
282282
secp256k1_scalar_negate(&cache_i.tweak, &cache_i.tweak);
283283
}
@@ -294,4 +294,12 @@ int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pub
294294
return 1;
295295
}
296296

297+
int secp256k1_musig_pubkey_ec_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) {
298+
return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 0);
299+
}
300+
301+
int secp256k1_musig_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) {
302+
return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 1);
303+
}
304+
297305
#endif

src/modules/musig/session_impl.h

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -538,56 +538,65 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p
538538
* The following public keys arise as intermediate steps:
539539
* - P[i] is the i-th public key with corresponding secret key x[i]
540540
* P[i] := x[i]*G
541-
* - P_agg is the aggregate public key
542-
* P_agg := mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|
543-
* - P_tweak[i] is the tweaked public key after the i-th tweaking operation
544-
* P_tweak[0] := P_agg
545-
* P_tweak[i] := |P_tweak[i-1]| + t[i]*G for i = 1, ..., m
541+
* - P_agg[0] is the aggregate public key
542+
* P_agg[0] := mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|
543+
* - P_agg[i] for 1 <= i <= m is the tweaked public key after the i-th
544+
* tweaking operation. There are two types of tweaking: x-only and ordinary
545+
* "EC" tweaking. We define a boolean predicate xonly(i) that is true if
546+
* the i-th tweaking operation is x-only tweaking and false otherwise
547+
* (ordinary tweaking).
548+
* Let
549+
* P_agg[i] := f(i, P_agg[i-1]) + t[i]*G for i = 1, ..., m
550+
* where f(i, X) := |X| if xonly(i)
551+
* f(i, X) := X otherwise
546552
*
547553
* Note that our goal is to produce a partial signature corresponding to
548-
* the final public key after m tweaking operations P_final = |P_tweak[m]|.
554+
* the final public key after m tweaking operations P_final = |P_agg[m]|.
549555
*
550-
* Define d[i], d_agg, and d_tweak[i] so that:
556+
* Define d[i] for 0 <= i <= n-1 and d_agg[i] for 0 <= i <= m so that:
551557
* - |P[i]| = d[i]*P[i]
552-
* - |P_agg| = d_agg*P_agg
553-
* - |P_tweak[i]| = d_tweak[i]*P_tweak[i]
558+
* - f(i+1, P_agg[i]) = d_agg[i]*P_agg[i] for 0 <= i <= m - 1
559+
* - |P_agg[m]| = d_agg[m]*P_agg[m]
554560
*
555-
* In other words, d[i] = 1 if P[i] has even y coordinate, -1 otherwise;
556-
* similarly for d_agg and d_tweak[i].
561+
* In other words, d[i] = 1 if P[i] has even y coordinate, -1 otherwise.
562+
* For 0 <= i <= m-1, d_agg[i] is -1 if and only if xonly(i+1) is true and
563+
* P_agg[i] has an odd Y coordinate.
557564
*
558-
* The (xonly) final public key is P_final = |P_tweak[m]|
559-
* = d_tweak[m]*P_tweak[m]
560-
* = d_tweak[m]*(|P_tweak[m-1]| + t[m]*G)
561-
* = d_tweak[m]*(d_tweak[m-1]*(|P_tweak[m-2]| + t[m-1]*G) + t[m]*G)
562-
* = d_tweak[m]*...*d_tweak[1]*|P_agg| + (d_tweak[m]*t[m]+...+*d_tweak[1]*t[1])*G.
563-
* To simplify the equation let us define
564-
* t := d_tweak[m]*t[m]+...+*d_tweak[1]*t[1]
565-
* d_tweak := d_tweak[m]*...*d_tweak[1].
565+
* The (x-only) final public key is P_final = |P_agg[m]|
566+
* = d_agg[m]*P_agg[m]
567+
* = d_agg[m]*(f(m, P_agg[m-1]) + t[m]*G)
568+
* = d_agg[m]*(d_agg[m-1]*(f(m-1, P_agg[m-2]) + t[m-1]*G) + t[m]*G)
569+
* = d_agg[m]*...*d_agg[0]*P_agg[0] + (d_agg[m]*t[m]+...+*d_agg[1]*t[1])*G.
570+
* To simplify the equation let us define
571+
* d_agg := d_agg[m]*...*d_agg[0].
572+
* t := d_agg[m]*t[m]+...+*d_agg[1]*t[1] if m > 0, otherwise t := 0
566573
* Then we have
567574
* P_final - t*G
568-
* = d_tweak*|P_agg|
569-
* = d_tweak*d_agg*P_agg
570-
* = d_tweak*d_agg*(mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|)
571-
* = d_tweak*d_agg*(d[0]*mu[0]*P[0] + ... + d[n-1]*mu[n-1]*P[n-1])
572-
* = sum((d_tweak*d_agg*d[i])*mu[i]*x[i])*G.
575+
* = d_agg*P_agg[0]
576+
* = d_agg*(mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|)
577+
* = d_agg*(d[0]*mu[0]*P[0] + ... + d[n-1]*mu[n-1]*P[n-1])
578+
* = sum((d_agg*d[i])*mu[i]*x[i])*G.
573579
*
574580
* Thus whether signer i should use the negated x[i] depends on the product
575-
* d_tweak[m]*...*d_tweak[1]*d_agg*d[i]. In other words, negate if and only
581+
* d_agg[m]*...*d_agg[1]*d_agg[0]*d[i]. In other words, negate if and only
576582
* if the following holds:
577-
* (P[i] has odd y) XOR (P_agg has odd y)
578-
* XOR (P_tweak[1] has odd y) XOR ... XOR (P_tweak[m] has odd y)
583+
* (P[i] has odd y) XOR (xonly(1) and P_agg[0] has odd y)
584+
* XOR (xonly(2) and P_agg[1] has odd y)
585+
* XOR ... XOR (xonly(m) and P_agg[m-1] has odd y)
586+
* XOR (P_agg[m] has odd y)
579587
*
580588
* Let us now look at how the terms in the equation correspond to the if
581589
* condition below for some values of m:
582-
* m = 0: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
583-
* P_agg has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
590+
* m = 0: P[i] has odd y = secp256k1_fe_is_odd(&pk.y)
591+
* P_agg[0] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
584592
* cache_i.internal_key_parity = 0
585-
* m = 1: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
586-
* P_agg has odd y = cache_i.internal_key_parity
587-
* P_tweak[1] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
588-
* m = 2: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
589-
* P_agg has odd y XOR P_tweak[1] has odd y = cache_i.internal_key_parity
590-
* P_tweak[2] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
593+
* m = 1: P[i] has odd y = secp256k1_fe_is_odd(&pk.y)
594+
* xonly(1) and P_agg[0] has odd y = cache_i.internal_key_parity
595+
* P_agg[1] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
596+
* m = 2: P[i] has odd y = secp256k1_fe_is_odd(&pk.y)
597+
* (xonly(1) and P_agg[0] has odd y)
598+
XOR (xonly(2) and P_agg[1] has odd y) = cache_i.internal_key_parity
599+
* P_agg[2] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
591600
* etc.
592601
*/
593602
if ((secp256k1_fe_is_odd(&pk.y)
@@ -674,7 +683,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
674683
/* When producing a partial signature, signer i uses a possibly
675684
* negated secret key:
676685
*
677-
* sk[i] = (d_tweak*d_agg*d[i])*x[i]
686+
* sk[i] = (d_agg*d[i])*x[i]
678687
*
679688
* to ensure that the aggregate signature will correspond to
680689
* an aggregate public key with even Y coordinate (see the
@@ -698,14 +707,14 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
698707
* The verifier doesn't have access to sk[i]*G, but can construct
699708
* it using the xonly public key |P[i]| as follows:
700709
*
701-
* sk[i]*G = d_tweak*d_agg*d[i]*x[i]*G
702-
* = d_tweak*d_agg*d[i]*P[i]
703-
* = d_tweak*d_agg*|P[i]|
710+
* sk[i]*G = d_agg*d[i]*x[i]*G
711+
* = d_agg*d[i]*P[i]
712+
* = d_agg*|P[i]|
704713
*
705-
* The if condition below is true whenever d_tweak*d_agg is
706-
* negative (again, see the explanation in musig_partial_sign). In
707-
* this case, the verifier negates e which will have the same end
708-
* result as negating |P[i]|, since they are multiplied later anyway.
714+
* The if condition below is true whenever d_agg is negative (again, see the
715+
* explanation in musig_partial_sign). In this case, the verifier negates e
716+
* which will have the same end result as negating |P[i]|, since they are
717+
* multiplied later anyway.
709718
*/
710719
if (secp256k1_fe_is_odd(&cache_i.pk.y)
711720
!= cache_i.internal_key_parity) {

0 commit comments

Comments
 (0)