musig: allow ordinary, non-xonly tweaking
This commit is contained in:
parent
c519b46879
commit
37107361a0
@ -241,16 +241,59 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get(
|
||||
secp256k1_musig_keyagg_cache *keyagg_cache
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak an x-only public key in a given keyagg_cache by adding
|
||||
* the generator multiplied with `tweak32` to it.
|
||||
/** Apply ordinary "EC" tweaking to a public key in a given keyagg_cache by
|
||||
* adding the generator multiplied with `tweak32` to it. This is useful for
|
||||
* deriving child keys from an aggregate public key via BIP32.
|
||||
*
|
||||
* The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after
|
||||
* the following pseudocode buf and buf2 have identical contents (absent
|
||||
* earlier failures).
|
||||
*
|
||||
* secp256k1_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...)
|
||||
* secp256k1_musig_pubkey_get(..., agg_pk, keyagg_cache)
|
||||
* secp256k1_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache)
|
||||
* secp256k1_ec_pubkey_serialize(..., buf, output_pk)
|
||||
* secp256k1_ec_pubkey_tweak_add(..., agg_pk, tweak32)
|
||||
* secp256k1_ec_pubkey_serialize(..., buf2, agg_pk)
|
||||
*
|
||||
* This function is required if you want to _sign_ for a tweaked aggregate key.
|
||||
* On the other hand, if you are only computing a public key, but not intending
|
||||
* to create a signature for it, you can just use
|
||||
* `secp256k1_ec_pubkey_tweak_add`.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid or the resulting public key would be
|
||||
* invalid (only when the tweak is the negation of the corresponding
|
||||
* secret key). 1 otherwise.
|
||||
* Args: ctx: pointer to a context object initialized for verification
|
||||
* Out: output_pubkey: pointer to a public key to store the result. Will be set
|
||||
* to an invalid value if this function returns 0. If you
|
||||
* do not need it, this arg can be NULL.
|
||||
* In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by
|
||||
* `musig_pubkey_agg`
|
||||
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid
|
||||
* according to `secp256k1_ec_seckey_verify`, this function
|
||||
* returns 0. For uniformly random 32-byte arrays the
|
||||
* chance of being invalid is negligible (around 1 in
|
||||
* 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT 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
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Apply x-only tweaking to a public key in a given keyagg_cache by adding the
|
||||
* generator multiplied with `tweak32` to it. This is useful for creating
|
||||
* Taproot outputs.
|
||||
*
|
||||
* The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in
|
||||
* the following pseudocode xonly_pubkey_tweak_add_check (absent earlier
|
||||
* failures) returns 1.
|
||||
*
|
||||
* secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...)
|
||||
* secp256k1_musig_pubkey_tweak_add(..., output_pubkey, tweak32, keyagg_cache)
|
||||
* secp256k1_xonly_pubkey_serialize(..., buf, output_pubkey)
|
||||
* secp256k1_musig_pubkey_xonly_tweak_add(..., output_pk, tweak32, keyagg_cache)
|
||||
* secp256k1_xonly_pubkey_serialize(..., buf, output_pk)
|
||||
* secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32)
|
||||
*
|
||||
* 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(
|
||||
* chance of being invalid is negligible (around 1 in
|
||||
* 2^128).
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_tweak_add(
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_tweak_add(
|
||||
const secp256k1_context* ctx,
|
||||
secp256k1_pubkey *output_pubkey,
|
||||
secp256k1_musig_keyagg_cache *keyagg_cache,
|
||||
|
@ -258,7 +258,7 @@ int secp256k1_musig_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *a
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) {
|
||||
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) {
|
||||
secp256k1_keyagg_cache_internal cache_i;
|
||||
int overflow = 0;
|
||||
secp256k1_scalar tweak;
|
||||
@ -277,7 +277,7 @@ int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pub
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
if (secp256k1_extrakeys_ge_even_y(&cache_i.pk)) {
|
||||
if (xonly && secp256k1_extrakeys_ge_even_y(&cache_i.pk)) {
|
||||
cache_i.internal_key_parity ^= 1;
|
||||
secp256k1_scalar_negate(&cache_i.tweak, &cache_i.tweak);
|
||||
}
|
||||
@ -294,4 +294,12 @@ int secp256k1_musig_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pub
|
||||
return 1;
|
||||
}
|
||||
|
||||
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) {
|
||||
return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 0);
|
||||
}
|
||||
|
||||
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) {
|
||||
return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -538,56 +538,65 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p
|
||||
* The following public keys arise as intermediate steps:
|
||||
* - P[i] is the i-th public key with corresponding secret key x[i]
|
||||
* P[i] := x[i]*G
|
||||
* - P_agg is the aggregate public key
|
||||
* P_agg := mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|
|
||||
* - P_tweak[i] is the tweaked public key after the i-th tweaking operation
|
||||
* P_tweak[0] := P_agg
|
||||
* P_tweak[i] := |P_tweak[i-1]| + t[i]*G for i = 1, ..., m
|
||||
* - P_agg[0] is the aggregate public key
|
||||
* P_agg[0] := mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|
|
||||
* - P_agg[i] for 1 <= i <= m is the tweaked public key after the i-th
|
||||
* tweaking operation. There are two types of tweaking: x-only and ordinary
|
||||
* "EC" tweaking. We define a boolean predicate xonly(i) that is true if
|
||||
* the i-th tweaking operation is x-only tweaking and false otherwise
|
||||
* (ordinary tweaking).
|
||||
* Let
|
||||
* P_agg[i] := f(i, P_agg[i-1]) + t[i]*G for i = 1, ..., m
|
||||
* where f(i, X) := |X| if xonly(i)
|
||||
* f(i, X) := X otherwise
|
||||
*
|
||||
* Note that our goal is to produce a partial signature corresponding to
|
||||
* the final public key after m tweaking operations P_final = |P_tweak[m]|.
|
||||
* the final public key after m tweaking operations P_final = |P_agg[m]|.
|
||||
*
|
||||
* Define d[i], d_agg, and d_tweak[i] so that:
|
||||
* Define d[i] for 0 <= i <= n-1 and d_agg[i] for 0 <= i <= m so that:
|
||||
* - |P[i]| = d[i]*P[i]
|
||||
* - |P_agg| = d_agg*P_agg
|
||||
* - |P_tweak[i]| = d_tweak[i]*P_tweak[i]
|
||||
* - f(i+1, P_agg[i]) = d_agg[i]*P_agg[i] for 0 <= i <= m - 1
|
||||
* - |P_agg[m]| = d_agg[m]*P_agg[m]
|
||||
*
|
||||
* In other words, d[i] = 1 if P[i] has even y coordinate, -1 otherwise;
|
||||
* similarly for d_agg and d_tweak[i].
|
||||
* In other words, d[i] = 1 if P[i] has even y coordinate, -1 otherwise.
|
||||
* For 0 <= i <= m-1, d_agg[i] is -1 if and only if xonly(i+1) is true and
|
||||
* P_agg[i] has an odd Y coordinate.
|
||||
*
|
||||
* The (xonly) final public key is P_final = |P_tweak[m]|
|
||||
* = d_tweak[m]*P_tweak[m]
|
||||
* = d_tweak[m]*(|P_tweak[m-1]| + t[m]*G)
|
||||
* = d_tweak[m]*(d_tweak[m-1]*(|P_tweak[m-2]| + t[m-1]*G) + t[m]*G)
|
||||
* = d_tweak[m]*...*d_tweak[1]*|P_agg| + (d_tweak[m]*t[m]+...+*d_tweak[1]*t[1])*G.
|
||||
* The (x-only) final public key is P_final = |P_agg[m]|
|
||||
* = d_agg[m]*P_agg[m]
|
||||
* = d_agg[m]*(f(m, P_agg[m-1]) + t[m]*G)
|
||||
* = d_agg[m]*(d_agg[m-1]*(f(m-1, P_agg[m-2]) + t[m-1]*G) + t[m]*G)
|
||||
* = d_agg[m]*...*d_agg[0]*P_agg[0] + (d_agg[m]*t[m]+...+*d_agg[1]*t[1])*G.
|
||||
* To simplify the equation let us define
|
||||
* t := d_tweak[m]*t[m]+...+*d_tweak[1]*t[1]
|
||||
* d_tweak := d_tweak[m]*...*d_tweak[1].
|
||||
* d_agg := d_agg[m]*...*d_agg[0].
|
||||
* t := d_agg[m]*t[m]+...+*d_agg[1]*t[1] if m > 0, otherwise t := 0
|
||||
* Then we have
|
||||
* P_final - t*G
|
||||
* = d_tweak*|P_agg|
|
||||
* = d_tweak*d_agg*P_agg
|
||||
* = d_tweak*d_agg*(mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|)
|
||||
* = d_tweak*d_agg*(d[0]*mu[0]*P[0] + ... + d[n-1]*mu[n-1]*P[n-1])
|
||||
* = sum((d_tweak*d_agg*d[i])*mu[i]*x[i])*G.
|
||||
* = d_agg*P_agg[0]
|
||||
* = d_agg*(mu[0]*|P[0]| + ... + mu[n-1]*|P[n-1]|)
|
||||
* = d_agg*(d[0]*mu[0]*P[0] + ... + d[n-1]*mu[n-1]*P[n-1])
|
||||
* = sum((d_agg*d[i])*mu[i]*x[i])*G.
|
||||
*
|
||||
* Thus whether signer i should use the negated x[i] depends on the product
|
||||
* d_tweak[m]*...*d_tweak[1]*d_agg*d[i]. In other words, negate if and only
|
||||
* d_agg[m]*...*d_agg[1]*d_agg[0]*d[i]. In other words, negate if and only
|
||||
* if the following holds:
|
||||
* (P[i] has odd y) XOR (P_agg has odd y)
|
||||
* XOR (P_tweak[1] has odd y) XOR ... XOR (P_tweak[m] has odd y)
|
||||
* (P[i] has odd y) XOR (xonly(1) and P_agg[0] has odd y)
|
||||
* XOR (xonly(2) and P_agg[1] has odd y)
|
||||
* XOR ... XOR (xonly(m) and P_agg[m-1] has odd y)
|
||||
* XOR (P_agg[m] has odd y)
|
||||
*
|
||||
* Let us now look at how the terms in the equation correspond to the if
|
||||
* condition below for some values of m:
|
||||
* m = 0: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
|
||||
* P_agg has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||
* m = 0: P[i] has odd y = secp256k1_fe_is_odd(&pk.y)
|
||||
* P_agg[0] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||
* cache_i.internal_key_parity = 0
|
||||
* m = 1: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
|
||||
* P_agg has odd y = cache_i.internal_key_parity
|
||||
* P_tweak[1] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||
* m = 2: P_i has odd y = secp256k1_fe_is_odd(&pk.y)
|
||||
* P_agg has odd y XOR P_tweak[1] has odd y = cache_i.internal_key_parity
|
||||
* P_tweak[2] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||
* m = 1: P[i] has odd y = secp256k1_fe_is_odd(&pk.y)
|
||||
* xonly(1) and P_agg[0] has odd y = cache_i.internal_key_parity
|
||||
* P_agg[1] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||
* m = 2: P[i] has odd y = secp256k1_fe_is_odd(&pk.y)
|
||||
* (xonly(1) and P_agg[0] has odd y)
|
||||
XOR (xonly(2) and P_agg[1] has odd y) = cache_i.internal_key_parity
|
||||
* P_agg[2] has odd y = secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||
* etc.
|
||||
*/
|
||||
if ((secp256k1_fe_is_odd(&pk.y)
|
||||
@ -674,7 +683,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
|
||||
/* When producing a partial signature, signer i uses a possibly
|
||||
* negated secret key:
|
||||
*
|
||||
* sk[i] = (d_tweak*d_agg*d[i])*x[i]
|
||||
* sk[i] = (d_agg*d[i])*x[i]
|
||||
*
|
||||
* to ensure that the aggregate signature will correspond to
|
||||
* 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
|
||||
* The verifier doesn't have access to sk[i]*G, but can construct
|
||||
* it using the xonly public key |P[i]| as follows:
|
||||
*
|
||||
* sk[i]*G = d_tweak*d_agg*d[i]*x[i]*G
|
||||
* = d_tweak*d_agg*d[i]*P[i]
|
||||
* = d_tweak*d_agg*|P[i]|
|
||||
* sk[i]*G = d_agg*d[i]*x[i]*G
|
||||
* = d_agg*d[i]*P[i]
|
||||
* = d_agg*|P[i]|
|
||||
*
|
||||
* The if condition below is true whenever d_tweak*d_agg is
|
||||
* negative (again, see the explanation in musig_partial_sign). In
|
||||
* this case, the verifier negates e which will have the same end
|
||||
* result as negating |P[i]|, since they are multiplied later anyway.
|
||||
* The if condition below is true whenever d_agg is negative (again, see the
|
||||
* explanation in musig_partial_sign). In this case, the verifier negates e
|
||||
* which will have the same end result as negating |P[i]|, since they are
|
||||
* multiplied later anyway.
|
||||
*/
|
||||
if (secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||
!= cache_i.internal_key_parity) {
|
||||
|
@ -254,38 +254,43 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
|
||||
CHECK(secp256k1_memcmp_var(&full_agg_pk, zeros68, sizeof(full_agg_pk)) == 0);
|
||||
|
||||
/** Tweaking **/
|
||||
ecount = 0;
|
||||
{
|
||||
int (*tweak_func[2]) (const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32);
|
||||
tweak_func[0] = secp256k1_musig_pubkey_ec_tweak_add;
|
||||
tweak_func[1] = secp256k1_musig_pubkey_xonly_tweak_add;
|
||||
for (i = 0; i < 2; i++) {
|
||||
secp256k1_pubkey tmp_output_pk;
|
||||
secp256k1_musig_keyagg_cache tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(ctx, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
ecount = 0;
|
||||
CHECK((*tweak_func[i])(ctx, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
/* Reset keyagg_cache */
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(none, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
CHECK((*tweak_func[i])(none, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(sign, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
CHECK((*tweak_func[i])(sign, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1);
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, NULL, &tmp_keyagg_cache, tweak) == 1);
|
||||
CHECK((*tweak_func[i])(vrfy, NULL, &tmp_keyagg_cache, tweak) == 1);
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_output_pk, NULL, tweak) == 0);
|
||||
CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, NULL, tweak) == 0);
|
||||
CHECK(ecount == 1);
|
||||
CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0);
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_output_pk, &tmp_keyagg_cache, NULL) == 0);
|
||||
CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, &tmp_keyagg_cache, NULL) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0);
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_output_pk, &tmp_keyagg_cache, max64) == 0);
|
||||
CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, &tmp_keyagg_cache, max64) == 0);
|
||||
CHECK(ecount == 2);
|
||||
CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0);
|
||||
tmp_keyagg_cache = keyagg_cache;
|
||||
/* Uninitialized keyagg_cache */
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_output_pk, &invalid_keyagg_cache, tweak) == 0);
|
||||
CHECK((*tweak_func[i])(vrfy, &tmp_output_pk, &invalid_keyagg_cache, tweak) == 0);
|
||||
CHECK(ecount == 3);
|
||||
CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros68, sizeof(tmp_output_pk.data)) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** Session creation **/
|
||||
ecount = 0;
|
||||
@ -851,7 +856,8 @@ void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const unsigne
|
||||
CHECK(secp256k1_schnorrsig_verify(ctx, final_sig, msg, sizeof(msg), agg_pk) == 1);
|
||||
}
|
||||
|
||||
/* Create aggregate public key P[0], tweak multiple times and test signing. */
|
||||
/* Create aggregate public key P[0], tweak multiple times (using xonly and
|
||||
* ordinary tweaking) and test signing. */
|
||||
void musig_tweak_test(secp256k1_scratch_space *scratch) {
|
||||
unsigned char sk[2][32];
|
||||
secp256k1_xonly_pubkey pk[2];
|
||||
@ -871,22 +877,35 @@ void musig_tweak_test(secp256k1_scratch_space *scratch) {
|
||||
/* Compute P0 = keyagg(pk0, pk1) and test signing for it */
|
||||
CHECK(secp256k1_musig_pubkey_agg(ctx, scratch, &P_xonly[0], &keyagg_cache, pk_ptr, 2) == 1);
|
||||
musig_tweak_test_helper(&P_xonly[0], sk[0], sk[1], &keyagg_cache);
|
||||
CHECK(secp256k1_musig_pubkey_get(ctx, &P[0], &keyagg_cache));
|
||||
|
||||
/* Compute Pi = |Pj| + tweaki*G where where j = i-1 and try signing for
|
||||
* that key. The function |.| normalizes the point to have an even
|
||||
* X-coordinate. This results in ordinary "xonly-tweaking". */
|
||||
/* Compute Pi = f(Pj) + tweaki*G where where j = i-1 and try signing for
|
||||
* that key. If xonly is set to true, the function f is normalizes the input
|
||||
* point to have an even X-coordinate ("xonly-tweaking").
|
||||
* Otherwise, the function f is the identity function. */
|
||||
for (i = 1; i < N_TWEAKS; i++) {
|
||||
unsigned char tweak[32];
|
||||
int P_parity;
|
||||
unsigned char P_serialized[32];
|
||||
int xonly = secp256k1_testrand_bits(1);
|
||||
|
||||
secp256k1_testrand256(tweak);
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(ctx, &P[i], &keyagg_cache, tweak) == 1);
|
||||
if (xonly) {
|
||||
CHECK(secp256k1_musig_pubkey_xonly_tweak_add(ctx, &P[i], &keyagg_cache, tweak) == 1);
|
||||
} else {
|
||||
CHECK(secp256k1_musig_pubkey_ec_tweak_add(ctx, &P[i], &keyagg_cache, tweak) == 1);
|
||||
}
|
||||
CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &P_xonly[i], &P_parity, &P[i]));
|
||||
CHECK(secp256k1_xonly_pubkey_serialize(ctx, P_serialized, &P_xonly[i]));
|
||||
/* Check that musig_pubkey_tweak_add produces same result as
|
||||
* xonly_pubkey_tweak_add. */
|
||||
* xonly_pubkey_tweak_add or ec_pubkey_tweak_add. */
|
||||
if (xonly) {
|
||||
unsigned char P_serialized[32];
|
||||
CHECK(secp256k1_xonly_pubkey_serialize(ctx, P_serialized, &P_xonly[i]));
|
||||
CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, P_serialized, P_parity, &P_xonly[i-1], tweak) == 1);
|
||||
} else {
|
||||
secp256k1_pubkey tmp_key = P[i-1];
|
||||
CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &tmp_key, tweak));
|
||||
CHECK(memcmp(&tmp_key, &P[i], sizeof(tmp_key)) == 0);
|
||||
}
|
||||
/* Test signing for P[i] */
|
||||
musig_tweak_test_helper(&P_xonly[i], sk[0], sk[1], &keyagg_cache);
|
||||
}
|
||||
@ -1145,7 +1164,7 @@ void musig_test_vectors_sign_helper(secp256k1_musig_keyagg_cache *keyagg_cache,
|
||||
}
|
||||
CHECK(secp256k1_musig_pubkey_agg(ctx, NULL, &agg_pk, keyagg_cache, pk_ptr, 3) == 1);
|
||||
if (tweak != NULL) {
|
||||
CHECK(secp256k1_musig_pubkey_tweak_add(ctx, NULL, keyagg_cache, tweak) == 1);
|
||||
CHECK(secp256k1_musig_pubkey_xonly_tweak_add(ctx, NULL, keyagg_cache, tweak) == 1);
|
||||
}
|
||||
memcpy(&secnonce.data[0], secp256k1_musig_secnonce_magic, 4);
|
||||
memcpy(&secnonce.data[4], secnonce_bytes, sizeof(secnonce.data) - 4);
|
||||
|
Loading…
x
Reference in New Issue
Block a user