musig: Re-add adaptor signatures support
This commit is contained in:
12
doc/musig.md
12
doc/musig.md
@@ -18,6 +18,7 @@ Therefore, users of the musig module must take great care to make sure of the fo
|
||||
See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`.
|
||||
3. Opaque data structures are never written to or read from directly.
|
||||
Instead, only the provided accessor functions are used.
|
||||
4. If adaptor signatures are used, all partial signatures are verified.
|
||||
|
||||
## Key Aggregation and (Taproot) Tweaking
|
||||
|
||||
@@ -52,3 +53,14 @@ Similarly, the API supports an alternative protocol flow where generating the ag
|
||||
## Verification
|
||||
|
||||
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.
|
||||
|
||||
# Atomic Swaps
|
||||
|
||||
The signing API supports the production of "adaptor signatures", modified partial signatures
|
||||
which are offset by an auxiliary secret known to one party. That is,
|
||||
1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`.
|
||||
2. When calling `secp256k1_musig_nonce_process`, the public adaptor `T` is provided as the `adaptor` argument.
|
||||
3. The party who is going to extract the secret adaptor `t` later must verify all partial signatures.
|
||||
4. Due to step 2, the signature output of `secp256k1_musig_partial_sig_agg` is a pre-signature and not a valid Schnorr signature. All parties involved extract this session's `nonce_parity` with `secp256k1_musig_nonce_parity`.
|
||||
5. The party who knows `t` must "adapt" the pre-signature with `t` (and the `nonce_parity` using `secp256k1_musig_adapt` to complete the signature.
|
||||
6. Any party who sees both the final signature and the pre-signature (and has the `nonce_parity`) can extract `t` with `secp256k1_musig_extract_adaptor`.
|
||||
|
||||
@@ -139,7 +139,7 @@ static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secr
|
||||
/* Every signer creates a partial signature */
|
||||
for (i = 0; i < N_SIGNERS; i++) {
|
||||
/* Initialize the signing session by processing the aggregate nonce */
|
||||
if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache)) {
|
||||
if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
/* partial_sign will clear the secnonce by setting it to 0. That's because
|
||||
|
||||
@@ -16,7 +16,7 @@ extern "C" {
|
||||
* v1.0.0. You can find an example demonstrating the musig module in
|
||||
* examples/musig.c.
|
||||
*
|
||||
* The module also supports BIP 341 ("Taproot") public key tweaking.
|
||||
* The module also supports BIP 341 ("Taproot") public key tweaking and adaptor signatures.
|
||||
*
|
||||
* It is recommended to read the documentation in this include file carefully.
|
||||
* Further notes on API usage can be found in doc/musig.md
|
||||
@@ -462,6 +462,11 @@ SECP256K1_API int secp256k1_musig_nonce_agg(
|
||||
/** Takes the aggregate nonce and creates a session that is required for signing
|
||||
* and verification of partial signatures.
|
||||
*
|
||||
* If the adaptor argument is non-NULL, then the output of
|
||||
* musig_partial_sig_agg will be a pre-signature which is not a valid Schnorr
|
||||
* signature. In order to create a valid signature, the pre-signature and the
|
||||
* secret adaptor must be provided to `musig_adapt`.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid, 1 otherwise
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: session: pointer to a struct to store the session
|
||||
@@ -470,13 +475,17 @@ SECP256K1_API int secp256k1_musig_nonce_agg(
|
||||
* msg32: the 32-byte message to sign
|
||||
* keyagg_cache: pointer to the keyagg_cache that was used to create the
|
||||
* aggregate (and potentially tweaked) pubkey
|
||||
* adaptor: optional pointer to an adaptor point encoded as a public
|
||||
* key if this signing session is part of an adaptor
|
||||
* signature protocol (can be NULL)
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process(
|
||||
const secp256k1_context *ctx,
|
||||
secp256k1_musig_session *session,
|
||||
const secp256k1_musig_aggnonce *aggnonce,
|
||||
const unsigned char *msg32,
|
||||
const secp256k1_musig_keyagg_cache *keyagg_cache
|
||||
const secp256k1_musig_keyagg_cache *keyagg_cache,
|
||||
const secp256k1_pubkey *adaptor
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
|
||||
|
||||
/** Produces a partial signature
|
||||
@@ -534,6 +543,7 @@ SECP256K1_API int secp256k1_musig_partial_sign(
|
||||
* before aggregating it with `musig_nonce_agg` and using the result to
|
||||
* create the `session` with `musig_nonce_process`.
|
||||
*
|
||||
* This function is essential when using protocols with adaptor signatures.
|
||||
* It is not required to call this function in regular MuSig sessions, because
|
||||
* if any partial signature does not verify, the final signature will not
|
||||
* verify either, so the problem will be caught. However, this function
|
||||
@@ -581,6 +591,77 @@ SECP256K1_API int secp256k1_musig_partial_sig_agg(
|
||||
size_t n_sigs
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Extracts the nonce_parity bit from a session
|
||||
*
|
||||
* This is used for adaptor signatures.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid, 1 otherwise
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: nonce_parity: pointer to an integer that indicates the parity
|
||||
* of the aggregate public nonce. Used for adaptor
|
||||
* signatures.
|
||||
* In: session: pointer to the session that was created with
|
||||
* musig_nonce_process
|
||||
*/
|
||||
SECP256K1_API int secp256k1_musig_nonce_parity(
|
||||
const secp256k1_context *ctx,
|
||||
int *nonce_parity,
|
||||
const secp256k1_musig_session *session
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Creates a signature from a pre-signature and an adaptor.
|
||||
*
|
||||
* If the sec_adaptor32 argument is incorrect, the output signature will be
|
||||
* invalid. This function does not verify the signature.
|
||||
*
|
||||
* Returns: 0 if the arguments are invalid, or pre_sig64 or sec_adaptor32 contain
|
||||
* invalid (overflowing) values. 1 otherwise (which does NOT mean the
|
||||
* signature or the adaptor are valid!)
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out: sig64: 64-byte signature. This pointer may point to the same
|
||||
* memory area as `pre_sig`.
|
||||
* In: pre_sig64: 64-byte pre-signature
|
||||
* sec_adaptor32: 32-byte secret adaptor to add to the pre-signature
|
||||
* nonce_parity: the output of `musig_nonce_parity` called with the
|
||||
* session used for producing the pre-signature
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_adapt(
|
||||
const secp256k1_context *ctx,
|
||||
unsigned char *sig64,
|
||||
const unsigned char *pre_sig64,
|
||||
const unsigned char *sec_adaptor32,
|
||||
int nonce_parity
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Extracts a secret adaptor from a MuSig pre-signature and corresponding
|
||||
* signature
|
||||
*
|
||||
* This function will not fail unless given grossly invalid data; if it is
|
||||
* merely given signatures that do not verify, the returned value will be
|
||||
* nonsense. It is therefore important that all data be verified at earlier
|
||||
* steps of any protocol that uses this function. In particular, this includes
|
||||
* verifying all partial signatures that were aggregated into pre_sig64.
|
||||
*
|
||||
* Returns: 0 if the arguments are NULL, or sig64 or pre_sig64 contain
|
||||
* grossly invalid (overflowing) values. 1 otherwise (which does NOT
|
||||
* mean the signatures or the adaptor are valid!)
|
||||
* Args: ctx: pointer to a context object
|
||||
* Out:sec_adaptor32: 32-byte secret adaptor
|
||||
* In: sig64: complete, valid 64-byte signature
|
||||
* pre_sig64: the pre-signature corresponding to sig64, i.e., the
|
||||
* aggregate of partial signatures without the secret
|
||||
* adaptor
|
||||
* nonce_parity: the output of `musig_nonce_parity` called with the
|
||||
* session used for producing sig64
|
||||
*/
|
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_extract_adaptor(
|
||||
const secp256k1_context *ctx,
|
||||
unsigned char *sec_adaptor32,
|
||||
const unsigned char *sig64,
|
||||
const unsigned char *pre_sig64,
|
||||
int nonce_parity
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -207,7 +207,12 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
|
||||
secp256k1_musig_keyagg_cache cache;
|
||||
secp256k1_musig_session session;
|
||||
secp256k1_musig_partial_sig partial_sig;
|
||||
const secp256k1_musig_partial_sig *partial_sig_ptr[1];
|
||||
unsigned char extra_input[32];
|
||||
unsigned char sec_adaptor[32];
|
||||
secp256k1_pubkey adaptor;
|
||||
unsigned char pre_sig[64];
|
||||
int nonce_parity;
|
||||
|
||||
pk_ptr[0] = &pk;
|
||||
pubnonce_ptr[0] = &pubnonce;
|
||||
@@ -216,14 +221,19 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
|
||||
session_secrand[0] = session_secrand[0] + 1;
|
||||
memcpy(extra_input, key, sizeof(extra_input));
|
||||
extra_input[0] = extra_input[0] + 2;
|
||||
memcpy(sec_adaptor, key, sizeof(sec_adaptor));
|
||||
sec_adaptor[0] = extra_input[0] + 3;
|
||||
partial_sig_ptr[0] = &partial_sig;
|
||||
|
||||
CHECK(secp256k1_keypair_create(ctx, &keypair, key));
|
||||
CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair));
|
||||
CHECK(secp256k1_musig_pubkey_agg(ctx, &agg_pk, &cache, pk_ptr, 1));
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &adaptor, sec_adaptor));
|
||||
|
||||
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
|
||||
SECP256K1_CHECKMEM_UNDEFINE(session_secrand, sizeof(session_secrand));
|
||||
SECP256K1_CHECKMEM_UNDEFINE(extra_input, sizeof(extra_input));
|
||||
SECP256K1_CHECKMEM_UNDEFINE(sec_adaptor, sizeof(sec_adaptor));
|
||||
ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_secrand, key, &pk, msg, &cache, extra_input);
|
||||
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
|
||||
CHECK(ret == 1);
|
||||
@@ -234,7 +244,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
|
||||
CHECK(secp256k1_musig_nonce_agg(ctx, &aggnonce, pubnonce_ptr, 1));
|
||||
/* Make sure that previous tests don't undefine msg. It's not used as a secret here. */
|
||||
SECP256K1_CHECKMEM_DEFINE(msg, sizeof(msg));
|
||||
CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache, &adaptor) == 1);
|
||||
|
||||
ret = secp256k1_keypair_create(ctx, &keypair, key);
|
||||
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
|
||||
@@ -242,6 +252,18 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
|
||||
ret = secp256k1_musig_partial_sign(ctx, &partial_sig, &secnonce, &keypair, &cache, &session);
|
||||
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
|
||||
CHECK(ret == 1);
|
||||
|
||||
SECP256K1_CHECKMEM_DEFINE(&partial_sig, sizeof(partial_sig));
|
||||
CHECK(secp256k1_musig_partial_sig_agg(ctx, pre_sig, &session, partial_sig_ptr, 1));
|
||||
SECP256K1_CHECKMEM_DEFINE(pre_sig, sizeof(pre_sig));
|
||||
|
||||
CHECK(secp256k1_musig_nonce_parity(ctx, &nonce_parity, &session));
|
||||
ret = secp256k1_musig_adapt(ctx, sig, pre_sig, sec_adaptor, nonce_parity);
|
||||
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
|
||||
CHECK(ret == 1);
|
||||
ret = secp256k1_musig_extract_adaptor(ctx, sec_adaptor, sig, pre_sig, nonce_parity);
|
||||
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
|
||||
CHECK(ret == 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,5 +4,6 @@ noinst_HEADERS += src/modules/musig/keyagg.h
|
||||
noinst_HEADERS += src/modules/musig/keyagg_impl.h
|
||||
noinst_HEADERS += src/modules/musig/session.h
|
||||
noinst_HEADERS += src/modules/musig/session_impl.h
|
||||
noinst_HEADERS += src/modules/musig/adaptor_impl.h
|
||||
noinst_HEADERS += src/modules/musig/tests_impl.h
|
||||
noinst_HEADERS += src/modules/musig/vectors.h
|
||||
|
||||
101
src/modules/musig/adaptor_impl.h
Normal file
101
src/modules/musig/adaptor_impl.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2021 Jonas Nick *
|
||||
* Distributed under the MIT software license, see the accompanying *
|
||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H
|
||||
#define SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../include/secp256k1.h"
|
||||
#include "../../../include/secp256k1_musig.h"
|
||||
|
||||
#include "session.h"
|
||||
#include "../../scalar.h"
|
||||
|
||||
int secp256k1_musig_nonce_parity(const secp256k1_context* ctx, int *nonce_parity, const secp256k1_musig_session *session) {
|
||||
secp256k1_musig_session_internal session_i;
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(nonce_parity != NULL);
|
||||
ARG_CHECK(session != NULL);
|
||||
|
||||
if (!secp256k1_musig_session_load(ctx, &session_i, session)) {
|
||||
return 0;
|
||||
}
|
||||
*nonce_parity = session_i.fin_nonce_parity;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_musig_adapt(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *pre_sig64, const unsigned char *sec_adaptor32, int nonce_parity) {
|
||||
secp256k1_scalar s;
|
||||
secp256k1_scalar t;
|
||||
int overflow;
|
||||
int ret = 1;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(sig64 != NULL);
|
||||
ARG_CHECK(pre_sig64 != NULL);
|
||||
ARG_CHECK(sec_adaptor32 != NULL);
|
||||
ARG_CHECK(nonce_parity == 0 || nonce_parity == 1);
|
||||
|
||||
secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_set_b32(&t, sec_adaptor32, &overflow);
|
||||
ret &= !overflow;
|
||||
|
||||
/* Determine if the secret adaptor should be negated.
|
||||
*
|
||||
* The musig_session stores the X-coordinate and the parity of the "final nonce"
|
||||
* (r + t)*G, where r*G is the aggregate public nonce and t is the secret adaptor.
|
||||
*
|
||||
* Since a BIP340 signature requires an x-only public nonce, in the case where
|
||||
* (r + t)*G has odd Y-coordinate (i.e. nonce_parity == 1), the x-only public nonce
|
||||
* corresponding to the signature is actually (-r - t)*G. Thus adapting a
|
||||
* pre-signature requires negating t in this case.
|
||||
*/
|
||||
if (nonce_parity) {
|
||||
secp256k1_scalar_negate(&t, &t);
|
||||
}
|
||||
|
||||
secp256k1_scalar_add(&s, &s, &t);
|
||||
secp256k1_scalar_get_b32(&sig64[32], &s);
|
||||
memmove(sig64, pre_sig64, 32);
|
||||
secp256k1_scalar_clear(&t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_musig_extract_adaptor(const secp256k1_context* ctx, unsigned char *sec_adaptor32, const unsigned char *sig64, const unsigned char *pre_sig64, int nonce_parity) {
|
||||
secp256k1_scalar t;
|
||||
secp256k1_scalar s;
|
||||
int overflow;
|
||||
int ret = 1;
|
||||
|
||||
VERIFY_CHECK(ctx != NULL);
|
||||
ARG_CHECK(sec_adaptor32 != NULL);
|
||||
ARG_CHECK(sig64 != NULL);
|
||||
ARG_CHECK(pre_sig64 != NULL);
|
||||
ARG_CHECK(nonce_parity == 0 || nonce_parity == 1);
|
||||
|
||||
secp256k1_scalar_set_b32(&t, &sig64[32], &overflow);
|
||||
ret &= !overflow;
|
||||
secp256k1_scalar_negate(&t, &t);
|
||||
|
||||
secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_add(&t, &t, &s);
|
||||
|
||||
if (!nonce_parity) {
|
||||
secp256k1_scalar_negate(&t, &t);
|
||||
}
|
||||
secp256k1_scalar_get_b32(sec_adaptor32, &t);
|
||||
secp256k1_scalar_clear(&t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -8,5 +8,6 @@
|
||||
|
||||
#include "keyagg_impl.h"
|
||||
#include "session_impl.h"
|
||||
#include "adaptor_impl.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -608,7 +608,7 @@ static void secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsign
|
||||
*fin_nonce_parity = secp256k1_fe_is_odd(&fin_nonce_pt.y);
|
||||
}
|
||||
|
||||
int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache) {
|
||||
int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey *adaptor) {
|
||||
secp256k1_keyagg_cache_internal cache_i;
|
||||
secp256k1_ge aggnonce_pts[2];
|
||||
unsigned char fin_nonce[32];
|
||||
@@ -630,6 +630,18 @@ int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add public adaptor to nonce */
|
||||
if (adaptor != NULL) {
|
||||
secp256k1_ge adaptorp;
|
||||
secp256k1_gej tmp;
|
||||
if (!secp256k1_pubkey_load(ctx, &adaptorp, adaptor)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_gej_set_ge(&tmp, &aggnonce_pts[0]);
|
||||
secp256k1_gej_add_ge_var(&tmp, &tmp, &adaptorp, NULL);
|
||||
secp256k1_ge_set_gej(&aggnonce_pts[0], &tmp);
|
||||
}
|
||||
|
||||
secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32);
|
||||
secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ static int create_keypair_and_pk(secp256k1_keypair *keypair, secp256k1_pubkey *p
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Just a simple (non-tweaked) 2-of-2 MuSig aggregate, sign, verify
|
||||
/* Just a simple (non-adaptor, non-tweaked) 2-of-2 MuSig aggregate, sign, verify
|
||||
* test. */
|
||||
static void musig_simple_test(void) {
|
||||
unsigned char sk[2][32];
|
||||
@@ -74,7 +74,7 @@ static void musig_simple_test(void) {
|
||||
|
||||
CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1);
|
||||
CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, NULL) == 1);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[i], &secnonce[i], &keypair[i], &keyagg_cache, &session) == 1);
|
||||
@@ -123,6 +123,7 @@ static void musig_api_tests(void) {
|
||||
const secp256k1_musig_partial_sig *partial_sig_ptr[2];
|
||||
secp256k1_musig_partial_sig invalid_partial_sig;
|
||||
const secp256k1_musig_partial_sig *invalid_partial_sig_ptr[2];
|
||||
unsigned char final_sig[64];
|
||||
unsigned char pre_sig[64];
|
||||
unsigned char buf[32];
|
||||
unsigned char sk[2][32];
|
||||
@@ -157,6 +158,10 @@ static void musig_api_tests(void) {
|
||||
const secp256k1_pubkey *invalid_pk_ptr2[2];
|
||||
const secp256k1_pubkey *invalid_pk_ptr3[3];
|
||||
unsigned char tweak[32];
|
||||
int nonce_parity;
|
||||
unsigned char sec_adaptor[32];
|
||||
unsigned char sec_adaptor1[32];
|
||||
secp256k1_pubkey adaptor;
|
||||
int i;
|
||||
|
||||
/** setup **/
|
||||
@@ -174,8 +179,10 @@ static void musig_api_tests(void) {
|
||||
memset(&invalid_pubnonce, 0, sizeof(invalid_pubnonce));
|
||||
memset(&invalid_session, 0, sizeof(invalid_session));
|
||||
|
||||
testrand256(sec_adaptor);
|
||||
testrand256(msg);
|
||||
testrand256(tweak);
|
||||
CHECK(secp256k1_ec_pubkey_create(CTX, &adaptor, sec_adaptor) == 1);
|
||||
for (i = 0; i < 2; i++) {
|
||||
pk_ptr[i] = &pk[i];
|
||||
invalid_pk_ptr2[i] = &invalid_pk;
|
||||
@@ -388,15 +395,17 @@ static void musig_api_tests(void) {
|
||||
}
|
||||
|
||||
/** Process nonces **/
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, (secp256k1_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, &adaptor) == 1);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache, &adaptor));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache, &adaptor));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, (secp256k1_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache, &adaptor));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache, &adaptor));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL, &adaptor));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache, &adaptor));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, NULL) == 1);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, (secp256k1_pubkey *)&invalid_pk));
|
||||
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, &adaptor) == 1);
|
||||
|
||||
memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp));
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session) == 1);
|
||||
@@ -481,6 +490,40 @@ static void musig_api_tests(void) {
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 0));
|
||||
CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 1) == 1);
|
||||
CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1);
|
||||
|
||||
/** Adaptor signature verification */
|
||||
CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity, &session) == 1);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, NULL, &session));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, &nonce_parity, NULL));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, &nonce_parity, &invalid_session));
|
||||
|
||||
CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, nonce_parity) == 1);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, NULL, pre_sig, sec_adaptor, 0));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, NULL, sec_adaptor, 0));
|
||||
CHECK(secp256k1_musig_adapt(CTX, final_sig, max64, sec_adaptor, 0) == 0);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, pre_sig, NULL, 0));
|
||||
CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, max64, 0) == 0);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, 2));
|
||||
/* sig and pre_sig argument point to the same location */
|
||||
memcpy(final_sig, pre_sig, sizeof(final_sig));
|
||||
CHECK(secp256k1_musig_adapt(CTX, final_sig, final_sig, sec_adaptor, nonce_parity) == 1);
|
||||
CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1);
|
||||
|
||||
CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, nonce_parity) == 1);
|
||||
CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1);
|
||||
|
||||
/** Secret adaptor can be extracted from signature */
|
||||
CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, nonce_parity) == 1);
|
||||
CHECK(secp256k1_memcmp_var(sec_adaptor, sec_adaptor1, 32) == 0);
|
||||
/* wrong nonce parity */
|
||||
CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, !nonce_parity) == 1);
|
||||
CHECK(secp256k1_memcmp_var(sec_adaptor, sec_adaptor1, 32) != 0);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, NULL, final_sig, pre_sig, 0));
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, NULL, pre_sig, 0));
|
||||
CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, max64, pre_sig, 0) == 0);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, NULL, 0));
|
||||
CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, max64, 0) == 0);
|
||||
CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, 2));
|
||||
}
|
||||
|
||||
static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
|
||||
@@ -548,6 +591,111 @@ static void musig_nonce_test(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void scriptless_atomic_swap(void) {
|
||||
/* Throughout this test "a" and "b" refer to two hypothetical blockchains,
|
||||
* while the indices 0 and 1 refer to the two signers. Here signer 0 is
|
||||
* sending a-coins to signer 1, while signer 1 is sending b-coins to signer
|
||||
* 0. Signer 0 produces the adaptor signatures. */
|
||||
unsigned char pre_sig_a[64];
|
||||
unsigned char final_sig_a[64];
|
||||
unsigned char pre_sig_b[64];
|
||||
unsigned char final_sig_b[64];
|
||||
secp256k1_musig_partial_sig partial_sig_a[2];
|
||||
const secp256k1_musig_partial_sig *partial_sig_a_ptr[2];
|
||||
secp256k1_musig_partial_sig partial_sig_b[2];
|
||||
const secp256k1_musig_partial_sig *partial_sig_b_ptr[2];
|
||||
unsigned char sec_adaptor[32];
|
||||
unsigned char sec_adaptor_extracted[32];
|
||||
secp256k1_pubkey pub_adaptor;
|
||||
unsigned char sk_a[2][32];
|
||||
unsigned char sk_b[2][32];
|
||||
secp256k1_keypair keypair_a[2];
|
||||
secp256k1_keypair keypair_b[2];
|
||||
secp256k1_pubkey pk_a[2];
|
||||
const secp256k1_pubkey *pk_a_ptr[2];
|
||||
secp256k1_pubkey pk_b[2];
|
||||
const secp256k1_pubkey *pk_b_ptr[2];
|
||||
secp256k1_musig_keyagg_cache keyagg_cache_a;
|
||||
secp256k1_musig_keyagg_cache keyagg_cache_b;
|
||||
secp256k1_xonly_pubkey agg_pk_a;
|
||||
secp256k1_xonly_pubkey agg_pk_b;
|
||||
secp256k1_musig_secnonce secnonce_a[2];
|
||||
secp256k1_musig_secnonce secnonce_b[2];
|
||||
secp256k1_musig_pubnonce pubnonce_a[2];
|
||||
secp256k1_musig_pubnonce pubnonce_b[2];
|
||||
const secp256k1_musig_pubnonce *pubnonce_ptr_a[2];
|
||||
const secp256k1_musig_pubnonce *pubnonce_ptr_b[2];
|
||||
secp256k1_musig_aggnonce aggnonce_a;
|
||||
secp256k1_musig_aggnonce aggnonce_b;
|
||||
secp256k1_musig_session session_a, session_b;
|
||||
int nonce_parity_a;
|
||||
int nonce_parity_b;
|
||||
unsigned char seed_a[2][32] = { "a0", "a1" };
|
||||
unsigned char seed_b[2][32] = { "b0", "b1" };
|
||||
const unsigned char msg32_a[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'a'};
|
||||
const unsigned char msg32_b[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'b'};
|
||||
int i;
|
||||
|
||||
/* Step 1: key setup */
|
||||
for (i = 0; i < 2; i++) {
|
||||
pk_a_ptr[i] = &pk_a[i];
|
||||
pk_b_ptr[i] = &pk_b[i];
|
||||
pubnonce_ptr_a[i] = &pubnonce_a[i];
|
||||
pubnonce_ptr_b[i] = &pubnonce_b[i];
|
||||
partial_sig_a_ptr[i] = &partial_sig_a[i];
|
||||
partial_sig_b_ptr[i] = &partial_sig_b[i];
|
||||
|
||||
testrand256(sk_a[i]);
|
||||
testrand256(sk_b[i]);
|
||||
CHECK(create_keypair_and_pk(&keypair_a[i], &pk_a[i], sk_a[i]) == 1);
|
||||
CHECK(create_keypair_and_pk(&keypair_b[i], &pk_b[i], sk_b[i]) == 1);
|
||||
}
|
||||
testrand256(sec_adaptor);
|
||||
CHECK(secp256k1_ec_pubkey_create(CTX, &pub_adaptor, sec_adaptor) == 1);
|
||||
|
||||
CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk_a, &keyagg_cache_a, pk_a_ptr, 2) == 1);
|
||||
CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk_b, &keyagg_cache_b, pk_b_ptr, 2) == 1);
|
||||
|
||||
CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_a[0], &pubnonce_a[0], seed_a[0], sk_a[0], &pk_a[0], NULL, NULL, NULL) == 1);
|
||||
CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_a[1], &pubnonce_a[1], seed_a[1], sk_a[1], &pk_a[1], NULL, NULL, NULL) == 1);
|
||||
CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_b[0], &pubnonce_b[0], seed_b[0], sk_b[0], &pk_b[0], NULL, NULL, NULL) == 1);
|
||||
CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_b[1], &pubnonce_b[1], seed_b[1], sk_b[1], &pk_b[1], NULL, NULL, NULL) == 1);
|
||||
|
||||
/* Step 2: Exchange nonces */
|
||||
CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce_a, pubnonce_ptr_a, 2) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session_a, &aggnonce_a, msg32_a, &keyagg_cache_a, &pub_adaptor) == 1);
|
||||
CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity_a, &session_a) == 1);
|
||||
CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce_b, pubnonce_ptr_b, 2) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session_b, &aggnonce_b, msg32_b, &keyagg_cache_b, &pub_adaptor) == 1);
|
||||
CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity_b, &session_b) == 1);
|
||||
|
||||
/* Step 3: Signer 0 produces partial signatures for both chains. */
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_a[0], &secnonce_a[0], &keypair_a[0], &keyagg_cache_a, &session_a) == 1);
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_b[0], &secnonce_b[0], &keypair_b[0], &keyagg_cache_b, &session_b) == 1);
|
||||
|
||||
/* Step 4: Signer 1 receives partial signatures, verifies them and creates a
|
||||
* partial signature to send B-coins to signer 0. */
|
||||
CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig_a[0], &pubnonce_a[0], &pk_a[0], &keyagg_cache_a, &session_a) == 1);
|
||||
CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig_b[0], &pubnonce_b[0], &pk_b[0], &keyagg_cache_b, &session_b) == 1);
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_b[1], &secnonce_b[1], &keypair_b[1], &keyagg_cache_b, &session_b) == 1);
|
||||
|
||||
/* Step 5: Signer 0 aggregates its own partial signature with the partial
|
||||
* signature from signer 1 and adapts it. This results in a complete
|
||||
* signature which is broadcasted by signer 0 to take B-coins. */
|
||||
CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig_b, &session_b, partial_sig_b_ptr, 2) == 1);
|
||||
CHECK(secp256k1_musig_adapt(CTX, final_sig_b, pre_sig_b, sec_adaptor, nonce_parity_b) == 1);
|
||||
CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_b, msg32_b, sizeof(msg32_b), &agg_pk_b) == 1);
|
||||
|
||||
/* Step 6: Signer 1 signs, extracts adaptor from the published signature,
|
||||
* and adapts the signature to take A-coins. */
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_a[1], &secnonce_a[1], &keypair_a[1], &keyagg_cache_a, &session_a) == 1);
|
||||
CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig_a, &session_a, partial_sig_a_ptr, 2) == 1);
|
||||
CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor_extracted, final_sig_b, pre_sig_b, nonce_parity_b) == 1);
|
||||
CHECK(secp256k1_memcmp_var(sec_adaptor_extracted, sec_adaptor, sizeof(sec_adaptor)) == 0); /* in real life we couldn't check this, of course */
|
||||
CHECK(secp256k1_musig_adapt(CTX, final_sig_a, pre_sig_a, sec_adaptor_extracted, nonce_parity_a) == 1);
|
||||
CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_a, msg32_a, sizeof(msg32_a), &agg_pk_a) == 1);
|
||||
}
|
||||
|
||||
static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) {
|
||||
secp256k1_sha256 sha;
|
||||
secp256k1_sha256_initialize_tagged(&sha, tag, taglen);
|
||||
@@ -616,7 +764,7 @@ static void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const
|
||||
CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_secrand[1], sk1, &pk[1], NULL, NULL, NULL) == 1);
|
||||
|
||||
CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache, NULL) == 1);
|
||||
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], keyagg_cache, &session) == 1);
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], keyagg_cache, &session) == 1);
|
||||
@@ -882,7 +1030,7 @@ static void musig_test_vectors_signverify(void) {
|
||||
CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL));
|
||||
|
||||
CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index]));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL));
|
||||
|
||||
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0])));
|
||||
musig_test_set_secnonce(&secnonce, vector->secnonces[0], &pubkey);
|
||||
@@ -922,8 +1070,9 @@ static void musig_test_vectors_signverify(void) {
|
||||
if (!expected) {
|
||||
continue;
|
||||
}
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL));
|
||||
|
||||
CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk));
|
||||
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0])));
|
||||
musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey);
|
||||
expected = c->error != MUSIG_SECNONCE;
|
||||
@@ -955,7 +1104,7 @@ static void musig_test_vectors_signverify(void) {
|
||||
|
||||
CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL));
|
||||
CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, c->nonce_indices_len) == 1);
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL));
|
||||
|
||||
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[c->signer_index], sizeof(vector->pubkeys[0])));
|
||||
|
||||
@@ -1010,7 +1159,7 @@ static void musig_test_vectors_tweak(void) {
|
||||
CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk));
|
||||
CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly));
|
||||
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache, NULL));
|
||||
|
||||
CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session));
|
||||
CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig));
|
||||
@@ -1046,7 +1195,7 @@ static void musig_test_vectors_sigagg(void) {
|
||||
|
||||
CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk32, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly));
|
||||
CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, c->aggnonce));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache));
|
||||
CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache, NULL));
|
||||
for (j = 0; j < c->psig_indices_len; j++) {
|
||||
CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]]));
|
||||
partial_sig_ptr[j] = &partial_sig[j];
|
||||
@@ -1127,6 +1276,7 @@ static void run_musig_tests(void) {
|
||||
for (i = 0; i < COUNT; i++) {
|
||||
/* Run multiple times to ensure that pk and nonce have different y
|
||||
* parities */
|
||||
scriptless_atomic_swap();
|
||||
musig_tweak_test();
|
||||
}
|
||||
sha256_tag_test();
|
||||
|
||||
Reference in New Issue
Block a user