musig-spec: move description of secret key negation to spec
Also fix bug in description that resulted in a wrong definition of t. And rename keyagg coefficient from 'mu' to 'a' since we don't use the term "musig coefficient" anymore and a is what is used in the paper.
This commit is contained in:
parent
633d01add0
commit
57eb6b4167
@ -191,11 +191,11 @@ The algorithm '''''Sign(secnonce, sk, session_ctx)''''' is defined as:
|
|||||||
* Let ''d' = int(sk)''
|
* Let ''d' = int(sk)''
|
||||||
* Fail if ''d' = 0'' or ''d' ≥ n''
|
* Fail if ''d' = 0'' or ''d' ≥ n''
|
||||||
* Let ''P = d'⋅G''
|
* Let ''P = d'⋅G''
|
||||||
* Let ''mu = GetSessionKeyAggCoeff(session_ctx, P)''; fail if that fails
|
* Let ''a = GetSessionKeyAggCoeff(session_ctx, P)''; fail if that fails
|
||||||
* Let ''g<sub>v</sub> = 1'' if ''has_even_y(Q)'', otherwise let ''g<sub>v</sub> = -1 mod n''
|
|
||||||
* Let ''gp = 1'' if ''has_even_y(P)'', otherwise let ''gp = -1 mod n''
|
* Let ''gp = 1'' if ''has_even_y(P)'', otherwise let ''gp = -1 mod n''
|
||||||
* Let ''d = g<sub>v</sub>⋅gacc<sub>v</sub>⋅gp⋅d' ''
|
* Let ''g<sub>v</sub> = 1'' if ''has_even_y(Q)'', otherwise let ''g<sub>v</sub> = -1 mod n''
|
||||||
* Let ''s = (k<sub>1</sub> + b⋅k<sub>2</sub> + e⋅mu⋅d) mod n''
|
* <div id="Sign negation"></div>Let ''d = g<sub>v</sub>⋅gacc<sub>v</sub>⋅gp⋅d' '' (See [[negation-of-the-secret-key-when-signing|Negation Of The Secret Key When Signing]])
|
||||||
|
* Let ''s = (k<sub>1</sub> + b⋅k<sub>2</sub> + e⋅a⋅d) mod n''
|
||||||
* Let ''psig = bytes(s)''
|
* Let ''psig = bytes(s)''
|
||||||
* Let ''pubnonce = cbytes(k'<sub>1</sub>⋅G) || cbytes(k'<sub>2</sub>⋅G)''
|
* Let ''pubnonce = cbytes(k'<sub>1</sub>⋅G) || cbytes(k'<sub>2</sub>⋅G)''
|
||||||
* If ''PartialSigVerifyInternal(psig, pubnonce, bytes(P), session_ctx)'' (see below) returns failure, abort<ref>Verifying the signature before leaving the signer prevents random or attacker provoked computation errors. This prevents publishing invalid signatures which may leak information about the secret key. It is recommended, but can be omitted if the computation cost is prohibitive.</ref>.
|
* If ''PartialSigVerifyInternal(psig, pubnonce, bytes(P), session_ctx)'' (see below) returns failure, abort<ref>Verifying the signature before leaving the signer prevents random or attacker provoked computation errors. This prevents publishing invalid signatures which may leak information about the secret key. It is recommended, but can be omitted if the computation cost is prohibitive.</ref>.
|
||||||
@ -236,9 +236,9 @@ The algorithm '''''PartialSigVerifyInternal(psig, pubnonce, pk<sup>*</sup>, sess
|
|||||||
* Let ''R<sup>*</sup> = R<sup>*</sup>' '' if ''has_even_y(R)'', otherwise let ''R<sup>*</sup> = -R<sup>*</sup>' ''
|
* Let ''R<sup>*</sup> = R<sup>*</sup>' '' if ''has_even_y(R)'', otherwise let ''R<sup>*</sup> = -R<sup>*</sup>' ''
|
||||||
* Let ''g<sub>v</sub> = 1'' if ''has_even_y(Q)'', otherwise let ''g<sub>v</sub> = -1 mod n''
|
* Let ''g<sub>v</sub> = 1'' if ''has_even_y(Q)'', otherwise let ''g<sub>v</sub> = -1 mod n''
|
||||||
* Let ''g' = g<sub>v</sub>⋅gacc<sub>v</sub> mod n''
|
* Let ''g' = g<sub>v</sub>⋅gacc<sub>v</sub> mod n''
|
||||||
* Let ''P = g'⋅point(pk<sup>*</sup>)''; fail if that fails
|
* <div id="SigVerify negation"></div>Let ''P = g'⋅point(pk<sup>*</sup>)''; fail if that fails (See [[#negation-of-the-public-key-when-partially-verifying|Negation Of The Public Key When Partially Verifying]])
|
||||||
* Let ''mu = GetSessionKeyAggCoeff(session_ctx, P)''; fail if that fails
|
* Let ''a = GetSessionKeyAggCoeff(session_ctx, P)''; fail if that fails
|
||||||
* Fail if ''s⋅G ≠ R<sup>*</sup> + e⋅mu⋅P''
|
* Fail if ''s⋅G ≠ R<sup>*</sup> + e⋅a⋅P''
|
||||||
* Return success iff no failure occurred before reaching this point.
|
* Return success iff no failure occurred before reaching this point.
|
||||||
|
|
||||||
==== Partial Signature Aggregation ====
|
==== Partial Signature Aggregation ====
|
||||||
@ -288,6 +288,90 @@ The algorithm '''''OrdinaryTweak(P, t)''''' is defined as:
|
|||||||
The algorithm '''''XonlyTweak(P, t)''''' is defined as:
|
The algorithm '''''XonlyTweak(P, t)''''' is defined as:
|
||||||
* Return ''with_even_y(P) + t⋅G''
|
* Return ''with_even_y(P) + t⋅G''
|
||||||
|
|
||||||
|
==== Negation Of The Secret Key When Signing ====
|
||||||
|
|
||||||
|
In order to produce a partial signature for an x-only public key that is an aggregate of ''u'' x-only keys and tweaked ''v'' times (x-only or ordinarily), the ''[[#Sign negation|Sign]]'' algorithm may need to negate the secret key during the signing process.
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
The following public keys arise as intermediate steps in the MuSig protocol:
|
||||||
|
• ''P<sub>i</sub>'' as computed in ''KeyAggInternal'' is the point corresponding to the ''i''-th signer's x-only public key. Defining ''d'<sub>i</sub>'' to be the ''d' '' value as computed in the ''Sign'' algorithm of the ''i''-th signer, we have
|
||||||
|
''P<sub>i</sub> = with_even_y(d'<sub>i</sub>⋅G) ''.
|
||||||
|
• ''Q<sub>0</sub>'' is an aggregate of the signer's public keys and defined in ''KeyAggInternal'' as
|
||||||
|
''Q<sub>0</sub> = a<sub>1</sub>⋅P<sub>1</sub> + a<sub>2</sub>⋅P<sub>1</sub> + ... + a<sub>u</sub>⋅P<sub>u</sub>''.
|
||||||
|
• ''Q<sub>i</sub>'' as computed in ''Tweak'' for ''1 ≤ i ≤ v'' is the tweaked public key after the ''i''-th tweaking operation. It holds that
|
||||||
|
''Q<sub>i</sub> = f(i-1) + t<sub>i</sub>⋅G'' for ''i = 1, ..., v'' where
|
||||||
|
''f(i) := with_even_y(Q<sub>i</sub>)'' if ''is_xonly_t<sub>i+1</sub>'' and
|
||||||
|
''f(i) := Q<sub>i</sub>'' otherwise.
|
||||||
|
</poem>
|
||||||
|
|
||||||
|
The goal is to produce a partial signature corresponding to the output of ''KeyAgg'', i.e., the final (x-only) public key point after ''v'' tweaking operations ''with_even_y(Q<sub>v</sub>)''.
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
We define ''gp<sub>i</sub>'' for ''1 ≤ i ≤ u'' to be ''gp '' as computed in the ''Sign'' algorithm of the ''i''-th signer. It holds that
|
||||||
|
''P<sub>i</sub> = gp<sub>i</sub>⋅d'<sub>i</sub>⋅G''.
|
||||||
|
|
||||||
|
For ''0 ≤ i ≤ v-1'', the ''Tweak'' algorithm called from ''KeyAggInternal'' sets ''g<sub>i</sub>'' to ''-1 mod n'' if and only if ''is_xonly_t<sub>i+1</sub>'' is true and ''Q<sub>i</sub>'' has an odd Y coordinate. Therefore, we have
|
||||||
|
''f(i) = g<sub>i</sub>⋅Q<sub>i</sub>'' for ''0 ≤ i ≤ v - 1''.
|
||||||
|
|
||||||
|
Furthermore, the ''Sign'' and ''PartialSigVerify'' algorithms set ''g<sub>v</sub>'' such that
|
||||||
|
''with_even_y(Q<sub>v</sub>) = g<sub>v</sub>⋅Q<sub>v</sub>''.
|
||||||
|
</poem>
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
So, the (x-only) final public key is
|
||||||
|
''with_even_y(Q<sub>v</sub>)
|
||||||
|
= g<sub>v</sub>⋅Q<sub>v</sub>
|
||||||
|
= g<sub>v</sub>⋅(f(v-1) + t<sub>v</sub>⋅G)
|
||||||
|
= g<sub>v</sub>⋅(g<sub>v-1</sub>⋅(f(v-2) + t<sub>v-1</sub>⋅G) + t<sub>v</sub>⋅G)
|
||||||
|
= g<sub>v</sub>⋅g<sub>v-1</sub>⋅f(v-2) + g<sub>v</sub>⋅(t<sub>v</sub> + g<sub>v-1</sub>⋅t<sub>v-1</sub>)⋅G
|
||||||
|
= g<sub>v</sub>⋅g<sub>v-1</sub>⋅f(v-2) + (sum<sub>i=v-1..v</sub> t<sub>i</sub>⋅prod<sub>j=i..v</sub> g<sub>j</sub>)⋅G
|
||||||
|
= g<sub>v</sub>⋅g<sub>v-1</sub>⋅...⋅g<sub>1</sub>⋅f(0) + (sum<sub>i=1..v</sub> t<sub>i</sub>⋅prod<sub>j=i..v</sub> g<sub>j</sub>)⋅G
|
||||||
|
= g<sub>v</sub>⋅...⋅g<sub>0</sub>⋅Q<sub>0</sub> + g<sub>v</sub>⋅tacc<sub>v</sub>⋅G''
|
||||||
|
where ''tacc<sub>i</sub>'' is computed by ''KeyAggInternal'' and ''Tweak'' as follows:
|
||||||
|
''tacc<sub>0</sub> = 0
|
||||||
|
tacc<sub>i</sub> = t<sub>i</sub> + g<sub>i-1</sub>⋅tacc<sub>i-1</sub> for i=1..v mod n''
|
||||||
|
for which it holds that ''g<sub>v</sub>⋅tacc<sub>v</sub> = sum<sub>i=1..v</sub> t<sub>i</sub>⋅prod<sub>j=i..v</sub> g<sub>j</sub>''.
|
||||||
|
</poem>
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
''KeyAggInternal'' and ''Tweak'' compute
|
||||||
|
''gacc<sub>0</sub> = 1
|
||||||
|
gacc<sub>i</sub> = g<sub>i-1</sub>⋅gacc<sub>i-1</sub> for i=1..v mod n''
|
||||||
|
So we can rewrite above equation for the final public key as
|
||||||
|
''with_even_y(Q<sub>v</sub>) = g<sub>v</sub>⋅gacc<sub>v</sub>⋅Q<sub>0</sub> + g<sub>v</sub>⋅tacc<sub>v</sub>⋅G''.
|
||||||
|
</poem>
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
Then we have
|
||||||
|
''with_even_y(Q<sub>v</sub>) - g<sub>v</sub>⋅tacc<sub>v</sub>⋅G
|
||||||
|
= g<sub>v</sub>⋅gacc<sub>v</sub>⋅Q<sub>0</sub>
|
||||||
|
= g<sub>v</sub>⋅gacc<sub>v</sub>⋅(a<sub>1</sub>⋅P<sub>1</sub> + ... + a<sub>u</sub>⋅P<sub>u</sub>)
|
||||||
|
= g<sub>v</sub>⋅gacc<sub>v</sub>⋅(a<sub>1</sub>⋅gp<sub>1</sub>⋅d'<sub>1</sub>⋅G + ... + a<sub>u</sub>⋅gp<sub>u</sub>⋅d'<sub>u</sub>⋅G)
|
||||||
|
= sum<sub>i=1..u</sub>(g<sub>v</sub>⋅gacc<sub>v</sub>⋅gp<sub>i</sub>⋅a<sub>i</sub>⋅d'<sub>i</sub>)*G''.
|
||||||
|
</poem>
|
||||||
|
|
||||||
|
Thus, signer ''i'' multiplies its secret key ''d'<sub>i</sub>'' with ''g<sub>v</sub>⋅gacc<sub>v</sub>⋅gp<sub>i</sub>'' in the ''[[#Sign negation|Sign]]'' algorithm.
|
||||||
|
|
||||||
|
==== Negation Of The Public Key When Partially Verifying ====
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
As explained in [[#negation-of-the-secret-key-when-signing|Negation Of The Secret Key When Signing]] the signer uses a possibly negated secret key
|
||||||
|
''d = g<sub>v</sub>⋅gacc<sub>v</sub>⋅gp⋅d' mod n''
|
||||||
|
when producing a partial signature to ensure that the aggregate signature will correspond to an aggregate public key with even Y coordinate.
|
||||||
|
</poem>
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
The ''[[#SigVerify negation|PartialSigVerifyInternal]]'' algorithm is supposed to check
|
||||||
|
''s⋅G = R<sup>*</sup> + e⋅a⋅d⋅G''.
|
||||||
|
</poem>
|
||||||
|
|
||||||
|
<poem>
|
||||||
|
The verifier doesn't have access to ''d⋅G'', but can construct it using the xonly public key ''pk<sup>*</sup>'' as follows:
|
||||||
|
''d⋅G
|
||||||
|
= g<sub>v</sub>⋅gacc<sub>v</sub>⋅gp⋅d'⋅G
|
||||||
|
= g<sub>v</sub>⋅gacc<sub>v</sub>⋅point(pk<sup>*</sup>)''
|
||||||
|
</poem>
|
||||||
|
|
||||||
==== Dealing with Infinity in Nonce Aggregation ====
|
==== Dealing with Infinity in Nonce Aggregation ====
|
||||||
|
|
||||||
If it happens that ''is_infinite(R'<sub>i</sub>)'' inside ''[[#NonceAgg infinity|NonceAgg]]'' there is at least one dishonest signer (except with negligible probability).
|
If it happens that ''is_infinite(R'<sub>i</sub>)'' inside ''[[#NonceAgg infinity|NonceAgg]]'' there is at least one dishonest signer (except with negligible probability).
|
||||||
|
@ -513,77 +513,17 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
secp256k1_fe_normalize_var(&pk.y);
|
secp256k1_fe_normalize_var(&pk.y);
|
||||||
/* Determine if the secret key sk should be negated before signing.
|
/* The specification requires that the secret key is multiplied by
|
||||||
*
|
* g*gp = g[0]*...g[v]*gp.
|
||||||
* We use the following notation:
|
* Since all factors are 1 or -1, the key is negated if and only if
|
||||||
* - |.| is a function that normalizes a point to an even Y by negating
|
* (P[i] has odd y) XOR (is_xonly_t[1] and Q[0] has odd y)
|
||||||
* if necessary, similar to secp256k1_extrakeys_ge_even_y
|
* XOR (is_xonly_t[2] and Q[1] has odd y)
|
||||||
* - mu[i] is the i-th KeyAgg coefficient
|
* XOR ... XOR (is_xonly_t[v] and Q[v-1] has odd y)
|
||||||
* - t[i] is the i-th tweak
|
* XOR (Q[v] has odd y)
|
||||||
*
|
* which is equivalent to
|
||||||
* The following public keys arise as intermediate steps:
|
* secp256k1_fe_is_odd(&pk.y)
|
||||||
* - P[i] is the i-th public key with corresponding secret key x[i]
|
* XOR cache_i.internal_key_parity
|
||||||
* P[i] := x[i]*G
|
* XOR secp256k1_fe_is_odd(&cache_i.pk.y)).
|
||||||
* - 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_agg[m]|.
|
|
||||||
*
|
|
||||||
* Define d[i] for 0 <= i <= n-1 and d_agg[i] for 0 <= i <= m so that:
|
|
||||||
* - |P[i]| = d[i]*P[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.
|
|
||||||
* 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 (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
|
|
||||||
* 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_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_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 (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[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)
|
|
||||||
* 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)
|
if ((secp256k1_fe_is_odd(&pk.y)
|
||||||
!= secp256k1_fe_is_odd(&cache_i.pk.y))
|
!= secp256k1_fe_is_odd(&cache_i.pk.y))
|
||||||
@ -659,41 +599,11 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
|
|||||||
secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp.x);
|
secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp.x);
|
||||||
secp256k1_scalar_mul(&e, &session_i.challenge, &mu);
|
secp256k1_scalar_mul(&e, &session_i.challenge, &mu);
|
||||||
|
|
||||||
/* When producing a partial signature, signer i uses a possibly
|
/* The specification requires that the public key is multiplied by g which
|
||||||
* negated secret key:
|
* is negative if and only if fe_is_odd(&cache_i.pk.y) XOR
|
||||||
*
|
* internal_key_parity. Instead of multiplying g with the public key, we
|
||||||
* sk[i] = (d_agg*d[i])*x[i]
|
* negate e which will have the same end result, since e and the public key
|
||||||
*
|
* are multiplied later anyway.
|
||||||
* to ensure that the aggregate signature will correspond to
|
|
||||||
* an aggregate public key with even Y coordinate (see the
|
|
||||||
* notation and explanation in musig_partial_sign).
|
|
||||||
*
|
|
||||||
* We use the following additional notation:
|
|
||||||
* - e is the (Schnorr signature) challenge
|
|
||||||
* - r[i] is the i-th signer's secret nonce
|
|
||||||
* - R[i] = r[i]*G is the i-th signer's public nonce
|
|
||||||
* - R is the aggregated public nonce
|
|
||||||
* - d_nonce is chosen so that |R| = d_nonce*R
|
|
||||||
*
|
|
||||||
* The i-th partial signature is:
|
|
||||||
*
|
|
||||||
* s[i] = d_nonce*r[i] + mu[i]*e*sk[i]
|
|
||||||
*
|
|
||||||
* In order to verify this partial signature, we need to check:
|
|
||||||
*
|
|
||||||
* s[i]*G = d_nonce*R[i] + mu[i]*e*sk[i]*G
|
|
||||||
*
|
|
||||||
* 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_agg*d[i]*x[i]*G
|
|
||||||
* = d_agg*d[i]*P[i]
|
|
||||||
* = d_agg*|P[i]|
|
|
||||||
*
|
|
||||||
* 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)
|
if (secp256k1_fe_is_odd(&cache_i.pk.y)
|
||||||
!= cache_i.internal_key_parity) {
|
!= cache_i.internal_key_parity) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user