Skip to content

Commit 7ad1220

Browse files
committed
fixup! address robot-dreams' and real-or-random's comments
1 parent a49168e commit 7ad1220

File tree

6 files changed

+70
-20
lines changed

6 files changed

+70
-20
lines changed

examples/musig.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct signer {
2828

2929
/* Number of public keys involved in creating the aggregate signature */
3030
#define N_SIGNERS 3
31-
/* Create a key pair and store it in seckey and pubkey */
31+
/* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */
3232
int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) {
3333
unsigned char seckey[32];
3434
FILE *frand = fopen("/dev/urandom", "r");
@@ -89,7 +89,8 @@ int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, st
8989
pubkeys[i] = &signer[i].pubkey;
9090
pubnonces[i] = &signer[i].pubnonce;
9191
}
92-
/* Communication round 1: Exchange nonces */
92+
/* Communication round 1: A production system would exchange public nonces
93+
* here before moving on. */
9394
for (i = 0; i < N_SIGNERS; i++) {
9495
secp256k1_musig_aggnonce agg_pubnonce;
9596

@@ -112,7 +113,8 @@ int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, st
112113
}
113114
partial_sigs[i] = &signer[i].partial_sig;
114115
}
115-
/* Communication round 2: Exchange partial signatures */
116+
/* Communication round 2: A production system would exchange
117+
* partial signatures here before moving on. */
116118
for (i = 0; i < N_SIGNERS; i++) {
117119
/* To check whether signing was successful, it suffices to either verify
118120
* the aggregate signature with the aggregate public key using

include/secp256k1_musig.h

+8-7
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extern "C" {
2424
*
2525
* You may know that the MuSig2 scheme uses two "nonces" instead of one. This
2626
* is not wrong, but only a technical detail we don't want to bother the user
27-
* with. Therefore, the API only uses to the singular term "nonce".
27+
* with. Therefore, the API only uses the singular term "nonce".
2828
*
2929
* Since the first version of MuSig is essentially replaced by MuSig2, when
3030
* writing MuSig or musig here we mean MuSig2.
@@ -121,7 +121,7 @@ SECP256K1_API int secp256k1_musig_pubnonce_parse(
121121
*
122122
* Returns: 1 when the nonce could be serialized, 0 otherwise
123123
* Args: ctx: a secp256k1 context object
124-
* Out: out32: pointer to a 66-byte array to store the serialized nonce
124+
* Out: out66: pointer to a 66-byte array to store the serialized nonce
125125
* In: nonce: pointer to the nonce
126126
*/
127127
SECP256K1_API int secp256k1_musig_pubnonce_serialize(
@@ -147,7 +147,7 @@ SECP256K1_API int secp256k1_musig_aggnonce_parse(
147147
*
148148
* Returns: 1 when the nonce could be serialized, 0 otherwise
149149
* Args: ctx: a secp256k1 context object
150-
* Out: out32: pointer to a 66-byte array to store the serialized nonce
150+
* Out: out66: pointer to a 66-byte array to store the serialized nonce
151151
* In: nonce: pointer to the nonce
152152
*/
153153
SECP256K1_API int secp256k1_musig_aggnonce_serialize(
@@ -260,7 +260,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_tweak_add(
260260
secp256k1_pubkey *output_pubkey,
261261
secp256k1_musig_keyagg_cache *keyagg_cache,
262262
const unsigned char *tweak32
263-
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
263+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
264264

265265
/** Starts a signing session by generating a nonce
266266
*
@@ -299,7 +299,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_tweak_add(
299299
* msg32: the 32-byte message that will later be signed, if already known
300300
* (can be NULL)
301301
* keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate
302-
* (and tweaked) public key if already known (can be NULL)
302+
* (and potentially tweaked) public key if already known
303+
* (can be NULL)
303304
* extra_input32: an optional 32-byte array that is input to the nonce
304305
* derivation function (can be NULL)
305306
*/
@@ -337,7 +338,7 @@ SECP256K1_API int secp256k1_musig_nonce_agg(
337338
size_t n_pubnonces
338339
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
339340

340-
/** Takes the public nonces of all signers and computes a session cache that is
341+
/** Takes the public nonces of all signers and computes a session that is
341342
* required for signing and verification of partial signatures.
342343
*
343344
* If the adaptor argument is non-NULL, then the output of
@@ -353,7 +354,7 @@ SECP256K1_API int secp256k1_musig_nonce_agg(
353354
* output of musig_nonce_agg
354355
* msg32: the 32-byte message to sign
355356
* keyagg_cache: pointer to the keyagg_cache that was used to create the
356-
* aggregate (and tweaked) pubkey
357+
* aggregate (and potentially tweaked) pubkey
357358
* adaptor: optional pointer to an adaptor point encoded as a public
358359
* key if this signing session is part of an adaptor
359360
* signature protocol (can be NULL)

src/modules/musig/adaptor_impl.h

+10
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ int secp256k1_musig_adapt(const secp256k1_context* ctx, unsigned char *sig64, co
4444
secp256k1_scalar_set_b32(&t, sec_adaptor32, &overflow);
4545
ret &= !overflow;
4646

47+
/* Determine if the secret adaptor should be negated.
48+
*
49+
* The musig_session stores the X-coordinate and the parity of the "final nonce"
50+
* (r + t)*G, where r*G is the aggregate public nonce and t is the secret adaptor.
51+
*
52+
* Since a BIP340 signature requires an x-only public nonce, in the case where
53+
* (r + t)*G has odd Y-coordinate (i.e. nonce_parity == 1), the x-only public nonce
54+
* corresponding to the signature is actually (-r - t)*G. Thus adapting a
55+
* presignature requires negating t in this case.
56+
*/
4757
if (nonce_parity) {
4858
secp256k1_scalar_negate(&t, &t);
4959
}

src/modules/musig/keyagg_impl.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,11 @@ int secp256k1_musig_pubkey_agg(const secp256k1_context* ctx, secp256k1_scratch_s
204204
/* No point on the curve has an X coordinate equal to 0 */
205205
secp256k1_fe_set_int(&ecmult_data.second_pk_x, 0);
206206
for (i = 1; i < n_pubkeys; i++) {
207-
secp256k1_ge pt;
208-
if (!secp256k1_xonly_pubkey_load(ctx, &pt, pubkeys[i])) {
209-
return 0;
210-
}
211207
if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) {
208+
secp256k1_ge pt;
209+
if (!secp256k1_xonly_pubkey_load(ctx, &pt, pubkeys[i])) {
210+
return 0;
211+
}
212212
ecmult_data.second_pk_x = pt.x;
213213
break;
214214
}

src/modules/musig/musig.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Similarly, the API supports an alternative protocol flow where generating the ag
4949

5050
# Verification
5151

52-
A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier does _not_ generate a nonce with `secp256k1_musig_nonce_gen`.
52+
A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7.
5353

5454
# Atomic Swaps
5555

src/modules/musig/session_impl.h

+42-5
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static const unsigned char secp256k1_musig_session_cache_magic[4] = { 0x9d, 0xed
8787
/* A session consists of
8888
* - 4 byte session cache magic
8989
* - 1 byte the parity of the final nonce
90-
* - 32 byte final nonce
90+
* - 32 byte serialized x-only final nonce
9191
* - 32 byte nonce coefficient b
9292
* - 32 byte signature challenge hash e
9393
* - 32 byte scalar s that is added to the partial signatures of the signers
@@ -386,7 +386,7 @@ int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggn
386386
return 1;
387387
}
388388

389-
/* hash(aggnonce[0], aggnonce[1], agg_pk, msg) */
389+
/* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */
390390
static int secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) {
391391
unsigned char buf[33];
392392
secp256k1_sha256 sha;
@@ -542,7 +542,7 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p
542542
* P_agg := mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|
543543
* - P_tweak[i] is the tweaked public key after the i-th tweaking operation
544544
* P_tweak[0] := P_agg
545-
* P_tweak[i] := |P_tweak[i-1]| + t[i]*G for i = 1, ..., m-1
545+
* P_tweak[i] := |P_tweak[i-1]| + t[i]*G for i = 1, ..., m
546546
*
547547
* Note that our goal is to produce a partial signature corresponding to
548548
* the final public key after m tweaking operations P_final = |P_tweak[m]|.
@@ -644,7 +644,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
644644
}
645645

646646
/* Compute "effective" nonce rj = aggnonce[0] + b*aggnonce[1] */
647-
/* TODO: use multiexp to compute -s*G + e*pubkey + aggnonce[0] + b*aggnonce[1] */
647+
/* TODO: use multiexp to compute -s*G + e*mu*pubkey + aggnonce[0] + b*aggnonce[1] */
648648
if (!secp256k1_musig_pubnonce_load(ctx, nonce_pt, pubnonce)) {
649649
return 0;
650650
}
@@ -670,6 +670,43 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
670670
* negated exactly when the aggregate key parity is odd. If the aggregate
671671
* key is tweaked, then negation happens when the aggregate key has an odd Y
672672
* coordinate XOR the internal key has an odd Y coordinate.*/
673+
674+
/* When producing a partial signature, signer i uses a possibly
675+
* negated secret key:
676+
*
677+
* sk[i] = (d_tweak*d_agg*d[i])*x[i]
678+
*
679+
* to ensure that the aggregate signature will correspond to
680+
* an aggregate public key with even Y coordinate (see the
681+
* notation and explanation in musig_partial_sign).
682+
*
683+
* We use the following additional notation:
684+
* - e is the (Schnorr signature) challenge
685+
* - r[i] is the i-th signer's secret nonce
686+
* - R[i] = r[i]*G is the i-th signer's public nonce
687+
* - R is the aggregated public nonce
688+
* - d_nonce is chosen so that |R| = d_nonce*R
689+
*
690+
* The i-th partial signature is:
691+
*
692+
* s[i] = d_nonce*r[i] + mu[i]*e*sk[i]
693+
*
694+
* In order to verify this partial signature, we need to check:
695+
*
696+
* s[i]*G = d_nonce*R[i] + mu[i]*e*sk[i]*G
697+
*
698+
* The verifier doesn't have access to sk[i]*G, but can construct
699+
* it using the xonly public key |P[i]| as follows:
700+
*
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]|
704+
*
705+
* The if condition is 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.
709+
*/
673710
if (secp256k1_fe_is_odd(&cache_i.pk.y)
674711
!= cache_i.internal_key_parity) {
675712
secp256k1_scalar_negate(&e, &e);
@@ -678,7 +715,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
678715
if (!secp256k1_musig_partial_sig_load(ctx, &s, partial_sig)) {
679716
return 0;
680717
}
681-
/* Compute -s*G + e*pkj + rj */
718+
/* Compute -s*G + e*pkj + rj (e already includes the keyagg coefficient mu) */
682719
secp256k1_scalar_negate(&s, &s);
683720
secp256k1_gej_set_ge(&pkj, &pkp);
684721
secp256k1_ecmult(&tmp, &pkj, &e, &s);

0 commit comments

Comments
 (0)