musig: simplify state machine by adding explicit round to session struct
This commit is contained in:
parent
6370bdd537
commit
29b4bd85d7
@ -45,14 +45,10 @@ typedef struct {
|
|||||||
* structure.
|
* structure.
|
||||||
*
|
*
|
||||||
* Fields:
|
* Fields:
|
||||||
* combined_pk: MuSig-computed combined xonly public key
|
* round: Current round of the session
|
||||||
* pre_session: Auxiliary data created in `pubkey_combine`
|
* pre_session: Auxiliary data created in `pubkey_combine`
|
||||||
|
* combined_pk: MuSig-computed combined xonly public key
|
||||||
* n_signers: Number of signers
|
* n_signers: Number of signers
|
||||||
* combined_nonce: Summed combined public nonce (undefined if `nonce_is_set` is false)
|
|
||||||
* nonce_is_set: Whether the above nonce has been set
|
|
||||||
* nonce_is_negated: If `nonce_is_set`, whether the above nonce was negated after
|
|
||||||
* summing the participants' nonces. Needed to ensure the nonce's y
|
|
||||||
* coordinate is even.
|
|
||||||
* msg: The 32-byte message (hash) to be signed
|
* msg: The 32-byte message (hash) to be signed
|
||||||
* msg_is_set: Whether the above message has been set
|
* msg_is_set: Whether the above message has been set
|
||||||
* has_secret_data: Whether this session object has a signers' secret data; if this
|
* has_secret_data: Whether this session object has a signers' secret data; if this
|
||||||
@ -60,18 +56,18 @@ typedef struct {
|
|||||||
* seckey: If `has_secret_data`, the signer's secret key
|
* seckey: If `has_secret_data`, the signer's secret key
|
||||||
* secnonce: If `has_secret_data`, the signer's secret nonce
|
* secnonce: If `has_secret_data`, the signer's secret nonce
|
||||||
* nonce: If `has_secret_data`, the signer's public nonce
|
* nonce: If `has_secret_data`, the signer's public nonce
|
||||||
* nonce_commitments_hash: If `has_secret_data` and `nonce_commitments_hash_is_set`,
|
* nonce_commitments_hash: If `has_secret_data` and round >= 1, the hash of all
|
||||||
* the hash of all signers' commitments
|
* signers' commitments
|
||||||
* nonce_commitments_hash_is_set: If `has_secret_data`, whether the
|
* combined_nonce: If round >= 2, the summed combined public nonce
|
||||||
* nonce_commitments_hash has been set
|
* nonce_is_negated: If round >= 2, whether the above nonce was negated after
|
||||||
|
* summing the participants' nonces. Needed to ensure the nonce's y
|
||||||
|
* coordinate is even.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
secp256k1_xonly_pubkey combined_pk;
|
int round;
|
||||||
secp256k1_musig_pre_session pre_session;
|
secp256k1_musig_pre_session pre_session;
|
||||||
|
secp256k1_xonly_pubkey combined_pk;
|
||||||
uint32_t n_signers;
|
uint32_t n_signers;
|
||||||
secp256k1_pubkey combined_nonce;
|
|
||||||
int nonce_is_set;
|
|
||||||
int nonce_is_negated;
|
|
||||||
unsigned char msg[32];
|
unsigned char msg[32];
|
||||||
int msg_is_set;
|
int msg_is_set;
|
||||||
int has_secret_data;
|
int has_secret_data;
|
||||||
@ -79,7 +75,8 @@ typedef struct {
|
|||||||
unsigned char secnonce[32];
|
unsigned char secnonce[32];
|
||||||
secp256k1_pubkey nonce;
|
secp256k1_pubkey nonce;
|
||||||
unsigned char nonce_commitments_hash[32];
|
unsigned char nonce_commitments_hash[32];
|
||||||
int nonce_commitments_hash_is_set;
|
secp256k1_pubkey combined_nonce;
|
||||||
|
int nonce_is_negated;
|
||||||
} secp256k1_musig_session;
|
} secp256k1_musig_session;
|
||||||
|
|
||||||
/** Data structure containing data on all signers in a single session.
|
/** Data structure containing data on all signers in a single session.
|
||||||
|
@ -140,6 +140,8 @@ int secp256k1_musig_session_initialize(const secp256k1_context* ctx, secp256k1_m
|
|||||||
secp256k1_sha256 sha;
|
secp256k1_sha256 sha;
|
||||||
secp256k1_gej pj;
|
secp256k1_gej pj;
|
||||||
secp256k1_ge p;
|
secp256k1_ge p;
|
||||||
|
unsigned char nonce_ser[33];
|
||||||
|
size_t nonce_ser_size = sizeof(nonce_ser);
|
||||||
|
|
||||||
VERIFY_CHECK(ctx != NULL);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
@ -162,7 +164,6 @@ int secp256k1_musig_session_initialize(const secp256k1_context* ctx, secp256k1_m
|
|||||||
}
|
}
|
||||||
memcpy(&session->combined_pk, combined_pk, sizeof(*combined_pk));
|
memcpy(&session->combined_pk, combined_pk, sizeof(*combined_pk));
|
||||||
session->pre_session = *pre_session;
|
session->pre_session = *pre_session;
|
||||||
session->nonce_is_set = 0;
|
|
||||||
session->has_secret_data = 1;
|
session->has_secret_data = 1;
|
||||||
if (n_signers == 0 || my_index >= n_signers) {
|
if (n_signers == 0 || my_index >= n_signers) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -172,7 +173,6 @@ int secp256k1_musig_session_initialize(const secp256k1_context* ctx, secp256k1_m
|
|||||||
}
|
}
|
||||||
session->n_signers = (uint32_t) n_signers;
|
session->n_signers = (uint32_t) n_signers;
|
||||||
secp256k1_musig_signers_init(signers, session->n_signers);
|
secp256k1_musig_signers_init(signers, session->n_signers);
|
||||||
session->nonce_commitments_hash_is_set = 0;
|
|
||||||
|
|
||||||
/* Compute secret key */
|
/* Compute secret key */
|
||||||
secp256k1_scalar_set_b32(&secret, seckey, &overflow);
|
secp256k1_scalar_set_b32(&secret, seckey, &overflow);
|
||||||
@ -223,15 +223,12 @@ int secp256k1_musig_session_initialize(const secp256k1_context* ctx, secp256k1_m
|
|||||||
secp256k1_ge_set_gej(&p, &pj);
|
secp256k1_ge_set_gej(&p, &pj);
|
||||||
secp256k1_pubkey_save(&session->nonce, &p);
|
secp256k1_pubkey_save(&session->nonce, &p);
|
||||||
|
|
||||||
if (nonce_commitment32 != NULL) {
|
secp256k1_sha256_initialize(&sha);
|
||||||
unsigned char commit[33];
|
secp256k1_ec_pubkey_serialize(ctx, nonce_ser, &nonce_ser_size, &session->nonce, SECP256K1_EC_COMPRESSED);
|
||||||
size_t commit_size = sizeof(commit);
|
secp256k1_sha256_write(&sha, nonce_ser, nonce_ser_size);
|
||||||
secp256k1_sha256_initialize(&sha);
|
secp256k1_sha256_finalize(&sha, nonce_commitment32);
|
||||||
secp256k1_ec_pubkey_serialize(ctx, commit, &commit_size, &session->nonce, SECP256K1_EC_COMPRESSED);
|
|
||||||
secp256k1_sha256_write(&sha, commit, commit_size);
|
|
||||||
secp256k1_sha256_finalize(&sha, nonce_commitment32);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
session->round = 0;
|
||||||
secp256k1_scalar_clear(&secret);
|
secp256k1_scalar_clear(&secret);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -247,6 +244,7 @@ int secp256k1_musig_session_get_public_nonce(const secp256k1_context* ctx, secp2
|
|||||||
ARG_CHECK(signers != NULL);
|
ARG_CHECK(signers != NULL);
|
||||||
ARG_CHECK(nonce != NULL);
|
ARG_CHECK(nonce != NULL);
|
||||||
ARG_CHECK(commitments != NULL);
|
ARG_CHECK(commitments != NULL);
|
||||||
|
ARG_CHECK(session->round == 0);
|
||||||
/* If the message was not set during initialization it must be set now. */
|
/* If the message was not set during initialization it must be set now. */
|
||||||
ARG_CHECK(!(!session->msg_is_set && msg32 == NULL));
|
ARG_CHECK(!(!session->msg_is_set && msg32 == NULL));
|
||||||
/* The message can only be set once. */
|
/* The message can only be set once. */
|
||||||
@ -269,15 +267,9 @@ int secp256k1_musig_session_get_public_nonce(const secp256k1_context* ctx, secp2
|
|||||||
secp256k1_sha256_write(&sha, commitments[i], 32);
|
secp256k1_sha256_write(&sha, commitments[i], 32);
|
||||||
}
|
}
|
||||||
secp256k1_sha256_finalize(&sha, nonce_commitments_hash);
|
secp256k1_sha256_finalize(&sha, nonce_commitments_hash);
|
||||||
if (session->nonce_commitments_hash_is_set
|
|
||||||
&& memcmp(session->nonce_commitments_hash, nonce_commitments_hash, 32) != 0) {
|
|
||||||
/* Abort if get_public_nonce has been called before with a different array of
|
|
||||||
* commitments. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memcpy(session->nonce_commitments_hash, nonce_commitments_hash, 32);
|
memcpy(session->nonce_commitments_hash, nonce_commitments_hash, 32);
|
||||||
session->nonce_commitments_hash_is_set = 1;
|
|
||||||
memcpy(nonce, &session->nonce, sizeof(*nonce));
|
memcpy(nonce, &session->nonce, sizeof(*nonce));
|
||||||
|
session->round = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,15 +305,14 @@ int secp256k1_musig_session_initialize_verifier(const secp256k1_context* ctx, se
|
|||||||
secp256k1_musig_signers_init(signers, session->n_signers);
|
secp256k1_musig_signers_init(signers, session->n_signers);
|
||||||
|
|
||||||
session->pre_session = *pre_session;
|
session->pre_session = *pre_session;
|
||||||
session->nonce_is_set = 0;
|
|
||||||
session->msg_is_set = 1;
|
session->msg_is_set = 1;
|
||||||
memcpy(session->msg, msg32, 32);
|
memcpy(session->msg, msg32, 32);
|
||||||
session->has_secret_data = 0;
|
session->has_secret_data = 0;
|
||||||
session->nonce_commitments_hash_is_set = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < n_signers; i++) {
|
for (i = 0; i < n_signers; i++) {
|
||||||
memcpy(signers[i].nonce_commitment, commitments[i], 32);
|
memcpy(signers[i].nonce_commitment, commitments[i], 32);
|
||||||
}
|
}
|
||||||
|
session->round = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,6 +349,7 @@ int secp256k1_musig_session_combine_nonces(const secp256k1_context* ctx, secp256
|
|||||||
VERIFY_CHECK(ctx != NULL);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
ARG_CHECK(session != NULL);
|
ARG_CHECK(session != NULL);
|
||||||
ARG_CHECK(signers != NULL);
|
ARG_CHECK(signers != NULL);
|
||||||
|
ARG_CHECK(session->round == 1);
|
||||||
|
|
||||||
if (n_signers != session->n_signers) {
|
if (n_signers != session->n_signers) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -373,16 +365,13 @@ int secp256k1_musig_session_combine_nonces(const secp256k1_context* ctx, secp256
|
|||||||
secp256k1_gej_add_ge_var(&combined_noncej, &combined_noncej, &noncep, NULL);
|
secp256k1_gej_add_ge_var(&combined_noncej, &combined_noncej, &noncep, NULL);
|
||||||
}
|
}
|
||||||
secp256k1_sha256_finalize(&sha, nonce_commitments_hash);
|
secp256k1_sha256_finalize(&sha, nonce_commitments_hash);
|
||||||
/* Either the session is a verifier session or or the nonce_commitments_hash has
|
/* If the signers' commitments changed between get_public_nonce and now we
|
||||||
* been set in `musig_session_get_public_nonce`. */
|
* have to abort because in that case they may have seen our nonce before
|
||||||
VERIFY_CHECK(!session->has_secret_data || session->nonce_commitments_hash_is_set);
|
* creating their commitment. That can happen if the signer_data given to
|
||||||
|
* this function is different to the signer_data given to get_public_nonce.
|
||||||
|
* */
|
||||||
if (session->has_secret_data
|
if (session->has_secret_data
|
||||||
&& memcmp(session->nonce_commitments_hash, nonce_commitments_hash, 32) != 0) {
|
&& memcmp(session->nonce_commitments_hash, nonce_commitments_hash, 32) != 0) {
|
||||||
/* If the signers' commitments changed between get_public_nonce and now we
|
|
||||||
* have to abort because in that case they may have seen our nonce before
|
|
||||||
* creating their commitment. That can happen if the signer_data given to
|
|
||||||
* this function is different to the signer_data given to get_public_nonce.
|
|
||||||
* */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +392,7 @@ int secp256k1_musig_session_combine_nonces(const secp256k1_context* ctx, secp256
|
|||||||
*nonce_is_negated = session->nonce_is_negated;
|
*nonce_is_negated = session->nonce_is_negated;
|
||||||
}
|
}
|
||||||
secp256k1_pubkey_save(&session->combined_nonce, &combined_noncep);
|
secp256k1_pubkey_save(&session->combined_nonce, &combined_noncep);
|
||||||
session->nonce_is_set = 1;
|
session->round = 2;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,19 +418,15 @@ static int secp256k1_musig_compute_messagehash(const secp256k1_context *ctx, uns
|
|||||||
secp256k1_ge rp;
|
secp256k1_ge rp;
|
||||||
secp256k1_sha256 sha;
|
secp256k1_sha256 sha;
|
||||||
|
|
||||||
|
VERIFY_CHECK(session->round >= 2);
|
||||||
|
|
||||||
secp256k1_schnorrsig_sha256_tagged(&sha);
|
secp256k1_schnorrsig_sha256_tagged(&sha);
|
||||||
if (!session->nonce_is_set) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
secp256k1_pubkey_load(ctx, &rp, &session->combined_nonce);
|
secp256k1_pubkey_load(ctx, &rp, &session->combined_nonce);
|
||||||
secp256k1_fe_get_b32(buf, &rp.x);
|
secp256k1_fe_get_b32(buf, &rp.x);
|
||||||
secp256k1_sha256_write(&sha, buf, 32);
|
secp256k1_sha256_write(&sha, buf, 32);
|
||||||
|
|
||||||
secp256k1_xonly_pubkey_serialize(ctx, buf, &session->combined_pk);
|
secp256k1_xonly_pubkey_serialize(ctx, buf, &session->combined_pk);
|
||||||
secp256k1_sha256_write(&sha, buf, 32);
|
secp256k1_sha256_write(&sha, buf, 32);
|
||||||
if (!session->msg_is_set) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
secp256k1_sha256_write(&sha, session->msg, 32);
|
secp256k1_sha256_write(&sha, session->msg, 32);
|
||||||
secp256k1_sha256_finalize(&sha, msghash);
|
secp256k1_sha256_finalize(&sha, msghash);
|
||||||
return 1;
|
return 1;
|
||||||
@ -456,8 +441,9 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, const secp256k1_m
|
|||||||
VERIFY_CHECK(ctx != NULL);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
ARG_CHECK(partial_sig != NULL);
|
ARG_CHECK(partial_sig != NULL);
|
||||||
ARG_CHECK(session != NULL);
|
ARG_CHECK(session != NULL);
|
||||||
|
ARG_CHECK(session->round == 2);
|
||||||
|
|
||||||
if (!session->nonce_is_set || !session->has_secret_data) {
|
if (!session->has_secret_data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,10 +489,8 @@ int secp256k1_musig_partial_sig_combine(const secp256k1_context* ctx, const secp
|
|||||||
ARG_CHECK(sig64 != NULL);
|
ARG_CHECK(sig64 != NULL);
|
||||||
ARG_CHECK(partial_sigs != NULL);
|
ARG_CHECK(partial_sigs != NULL);
|
||||||
ARG_CHECK(session != NULL);
|
ARG_CHECK(session != NULL);
|
||||||
|
ARG_CHECK(session->round == 2);
|
||||||
|
|
||||||
if (!session->nonce_is_set) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (n_sigs != session->n_signers) {
|
if (n_sigs != session->n_signers) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -548,8 +532,9 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
|
|||||||
ARG_CHECK(signer != NULL);
|
ARG_CHECK(signer != NULL);
|
||||||
ARG_CHECK(partial_sig != NULL);
|
ARG_CHECK(partial_sig != NULL);
|
||||||
ARG_CHECK(pubkey != NULL);
|
ARG_CHECK(pubkey != NULL);
|
||||||
|
ARG_CHECK(session->round == 2);
|
||||||
|
|
||||||
if (!session->nonce_is_set || !signer->present) {
|
if (!signer->present) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
secp256k1_scalar_set_b32(&s, partial_sig->data, &overflow);
|
secp256k1_scalar_set_b32(&s, partial_sig->data, &overflow);
|
||||||
|
@ -93,7 +93,6 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
|
|||||||
int nonce_is_negated;
|
int nonce_is_negated;
|
||||||
const unsigned char *ncs[2];
|
const unsigned char *ncs[2];
|
||||||
unsigned char msg[32];
|
unsigned char msg[32];
|
||||||
unsigned char msghash[32];
|
|
||||||
secp256k1_xonly_pubkey combined_pk;
|
secp256k1_xonly_pubkey combined_pk;
|
||||||
secp256k1_musig_pre_session pre_session;
|
secp256k1_musig_pre_session pre_session;
|
||||||
secp256k1_musig_pre_session pre_session_uninitialized;
|
secp256k1_musig_pre_session pre_session_uninitialized;
|
||||||
@ -234,37 +233,41 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
|
|||||||
CHECK(ecount == 5);
|
CHECK(ecount == 5);
|
||||||
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, &pre_session, ncs, 2) == 1);
|
CHECK(secp256k1_musig_session_initialize_verifier(none, &verifier_session, verifier_signer_data, msg, &combined_pk, &pre_session, ncs, 2) == 1);
|
||||||
|
|
||||||
CHECK(secp256k1_musig_compute_messagehash(none, msghash, &verifier_session) == 0);
|
|
||||||
CHECK(secp256k1_musig_compute_messagehash(none, msghash, &session[0]) == 0);
|
|
||||||
|
|
||||||
/** Signing step 0 -- exchange nonce commitments */
|
/** Signing step 0 -- exchange nonce commitments */
|
||||||
ecount = 0;
|
ecount = 0;
|
||||||
{
|
{
|
||||||
secp256k1_pubkey nonce;
|
secp256k1_pubkey nonce;
|
||||||
|
secp256k1_musig_session session_0_tmp;
|
||||||
|
|
||||||
|
memcpy(&session_0_tmp, &session[0], sizeof(session_0_tmp));
|
||||||
|
|
||||||
/* Can obtain public nonce after commitments have been exchanged; still can't sign */
|
/* Can obtain public nonce after commitments have been exchanged; still can't sign */
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &nonce, ncs, 2, NULL) == 1);
|
CHECK(secp256k1_musig_session_get_public_nonce(none, &session_0_tmp, signer0, &nonce, ncs, 2, NULL) == 1);
|
||||||
CHECK(secp256k1_musig_partial_sign(none, &session[0], &partial_sig[0]) == 0);
|
CHECK(secp256k1_musig_partial_sign(none, &session_0_tmp, &partial_sig[0]) == 0);
|
||||||
CHECK(ecount == 0);
|
CHECK(ecount == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Signing step 1 -- exchange nonces */
|
/** Signing step 1 -- exchange nonces */
|
||||||
ecount = 0;
|
ecount = 0;
|
||||||
{
|
{
|
||||||
secp256k1_pubkey public_nonce[3];
|
secp256k1_pubkey public_nonce[3];
|
||||||
|
secp256k1_musig_session session_0_tmp;
|
||||||
|
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 2, NULL) == 1);
|
memcpy(&session_0_tmp, &session[0], sizeof(session_0_tmp));
|
||||||
|
CHECK(secp256k1_musig_session_get_public_nonce(none, &session_0_tmp, signer0, &public_nonce[0], ncs, 2, NULL) == 1);
|
||||||
CHECK(ecount == 0);
|
CHECK(ecount == 0);
|
||||||
|
/* Reset session */
|
||||||
|
memcpy(&session_0_tmp, &session[0], sizeof(session_0_tmp));
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, NULL, signer0, &public_nonce[0], ncs, 2, NULL) == 0);
|
CHECK(secp256k1_musig_session_get_public_nonce(none, NULL, signer0, &public_nonce[0], ncs, 2, NULL) == 0);
|
||||||
CHECK(ecount == 1);
|
CHECK(ecount == 1);
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], NULL, &public_nonce[0], ncs, 2, NULL) == 0);
|
CHECK(secp256k1_musig_session_get_public_nonce(none, &session_0_tmp, NULL, &public_nonce[0], ncs, 2, NULL) == 0);
|
||||||
CHECK(ecount == 2);
|
CHECK(ecount == 2);
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, NULL, ncs, 2, NULL) == 0);
|
CHECK(secp256k1_musig_session_get_public_nonce(none, &session_0_tmp, signer0, NULL, ncs, 2, NULL) == 0);
|
||||||
CHECK(ecount == 3);
|
CHECK(ecount == 3);
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], NULL, 2, NULL) == 0);
|
CHECK(secp256k1_musig_session_get_public_nonce(none, &session_0_tmp, signer0, &public_nonce[0], NULL, 2, NULL) == 0);
|
||||||
CHECK(ecount == 4);
|
CHECK(ecount == 4);
|
||||||
/* Number of commitments and number of signers are different */
|
/* Number of commitments and number of signers are different */
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 1, NULL) == 0);
|
CHECK(secp256k1_musig_session_get_public_nonce(none, &session_0_tmp, signer0, &public_nonce[0], ncs, 1, NULL) == 0);
|
||||||
CHECK(ecount == 4);
|
CHECK(ecount == 4);
|
||||||
|
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 2, NULL) == 1);
|
CHECK(secp256k1_musig_session_get_public_nonce(none, &session[0], signer0, &public_nonce[0], ncs, 2, NULL) == 1);
|
||||||
@ -287,17 +290,20 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
|
|||||||
CHECK(secp256k1_musig_set_nonce(none, &verifier_signer_data[1], &public_nonce[1]) == 1);
|
CHECK(secp256k1_musig_set_nonce(none, &verifier_signer_data[1], &public_nonce[1]) == 1);
|
||||||
|
|
||||||
ecount = 0;
|
ecount = 0;
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, &session[0], signer0, 2, &nonce_is_negated, &adaptor) == 1);
|
memcpy(&session_0_tmp, &session[0], sizeof(session_0_tmp));
|
||||||
|
CHECK(secp256k1_musig_session_combine_nonces(none, &session_0_tmp, signer0, 2, &nonce_is_negated, &adaptor) == 1);
|
||||||
|
memcpy(&session_0_tmp, &session[0], sizeof(session_0_tmp));
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, NULL, signer0, 2, &nonce_is_negated, &adaptor) == 0);
|
CHECK(secp256k1_musig_session_combine_nonces(none, NULL, signer0, 2, &nonce_is_negated, &adaptor) == 0);
|
||||||
CHECK(ecount == 1);
|
CHECK(ecount == 1);
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, &session[0], NULL, 2, &nonce_is_negated, &adaptor) == 0);
|
CHECK(secp256k1_musig_session_combine_nonces(none, &session_0_tmp, NULL, 2, &nonce_is_negated, &adaptor) == 0);
|
||||||
CHECK(ecount == 2);
|
CHECK(ecount == 2);
|
||||||
/* Number of signers differs from number during intialization */
|
/* Number of signers differs from number during intialization */
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, &session[0], signer0, 1, &nonce_is_negated, &adaptor) == 0);
|
CHECK(secp256k1_musig_session_combine_nonces(none, &session_0_tmp, signer0, 1, &nonce_is_negated, &adaptor) == 0);
|
||||||
CHECK(ecount == 2);
|
CHECK(ecount == 2);
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, &session[0], signer0, 2, NULL, &adaptor) == 1);
|
CHECK(secp256k1_musig_session_combine_nonces(none, &session_0_tmp, signer0, 2, NULL, &adaptor) == 1);
|
||||||
CHECK(ecount == 2);
|
CHECK(ecount == 2);
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, &session[0], signer0, 2, &nonce_is_negated, NULL) == 1);
|
memcpy(&session_0_tmp, &session[0], sizeof(session_0_tmp));
|
||||||
|
CHECK(secp256k1_musig_session_combine_nonces(none, &session_0_tmp, signer0, 2, &nonce_is_negated, NULL) == 1);
|
||||||
|
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, &session[0], signer0, 2, &nonce_is_negated, &adaptor) == 1);
|
CHECK(secp256k1_musig_session_combine_nonces(none, &session[0], signer0, 2, &nonce_is_negated, &adaptor) == 1);
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(none, &session[1], signer0, 2, &nonce_is_negated, &adaptor) == 1);
|
CHECK(secp256k1_musig_session_combine_nonces(none, &session[1], signer0, 2, &nonce_is_negated, &adaptor) == 1);
|
||||||
@ -550,43 +556,8 @@ void musig_state_machine_late_msg_test(secp256k1_xonly_pubkey *pks, secp256k1_xo
|
|||||||
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session, &signers[1], &partial_sig, &pks[1]));
|
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session, &signers[1], &partial_sig, &pks[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recreates a session with the given session_id, signers, pk, msg etc. parameters
|
|
||||||
* and tries to verify and combine partial sigs. If do_combine is 0, the
|
|
||||||
* combine_nonces step is left out. In that case verify and combine should fail and
|
|
||||||
* this function should return 0. */
|
|
||||||
int musig_state_machine_missing_combine_test(secp256k1_xonly_pubkey *pks, secp256k1_xonly_pubkey *combined_pk, secp256k1_musig_pre_session *pre_session, unsigned char *nonce_commitment_other, secp256k1_pubkey *nonce_other, secp256k1_musig_partial_signature *partial_sig_other, unsigned char *msg, unsigned char *sk, unsigned char *session_id, secp256k1_musig_partial_signature *partial_sig, int do_combine) {
|
|
||||||
secp256k1_musig_session session;
|
|
||||||
secp256k1_musig_session_signer_data signers[2];
|
|
||||||
unsigned char nonce_commitment[32];
|
|
||||||
const unsigned char *ncs[2];
|
|
||||||
secp256k1_pubkey nonce;
|
|
||||||
secp256k1_musig_partial_signature partial_sigs[2];
|
|
||||||
unsigned char sig[64];
|
|
||||||
int partial_verify, sig_combine;
|
|
||||||
|
|
||||||
CHECK(secp256k1_musig_session_initialize(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pre_session, 2, 1, sk) == 1);
|
|
||||||
ncs[0] = nonce_commitment_other;
|
|
||||||
ncs[1] = nonce_commitment;
|
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session, signers, &nonce, ncs, 2, NULL) == 1);
|
|
||||||
CHECK(secp256k1_musig_set_nonce(ctx, &signers[0], nonce_other) == 1);
|
|
||||||
CHECK(secp256k1_musig_set_nonce(ctx, &signers[1], &nonce) == 1);
|
|
||||||
|
|
||||||
partial_sigs[0] = *partial_sig_other;
|
|
||||||
partial_sigs[1] = *partial_sig;
|
|
||||||
if (do_combine != 0) {
|
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(ctx, &session, signers, 2, NULL, NULL) == 1);
|
|
||||||
}
|
|
||||||
partial_verify = secp256k1_musig_partial_sig_verify(ctx, &session, signers, partial_sig_other, &pks[0]);
|
|
||||||
sig_combine = secp256k1_musig_partial_sig_combine(ctx, &session, sig, partial_sigs, 2);
|
|
||||||
if (do_combine != 0) {
|
|
||||||
/* Return 1 if both succeeded */
|
|
||||||
return partial_verify && sig_combine;
|
|
||||||
}
|
|
||||||
/* Return 0 if both failed */
|
|
||||||
return partial_verify || sig_combine;
|
|
||||||
}
|
|
||||||
|
|
||||||
void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
|
void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
|
||||||
|
secp256k1_context *ctx_tmp = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_VERIFY);
|
||||||
size_t i;
|
size_t i;
|
||||||
secp256k1_musig_session session[2];
|
secp256k1_musig_session session[2];
|
||||||
secp256k1_musig_session_signer_data signers0[2];
|
secp256k1_musig_session_signer_data signers0[2];
|
||||||
@ -601,8 +572,13 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
|
|||||||
secp256k1_pubkey nonce[2];
|
secp256k1_pubkey nonce[2];
|
||||||
const unsigned char *ncs[2];
|
const unsigned char *ncs[2];
|
||||||
secp256k1_musig_partial_signature partial_sig[2];
|
secp256k1_musig_partial_signature partial_sig[2];
|
||||||
|
unsigned char sig[64];
|
||||||
unsigned char msghash1[32];
|
unsigned char msghash1[32];
|
||||||
unsigned char msghash2[32];
|
unsigned char msghash2[32];
|
||||||
|
int ecount;
|
||||||
|
|
||||||
|
secp256k1_context_set_illegal_callback(ctx_tmp, counting_illegal_callback_fn, &ecount);
|
||||||
|
ecount = 0;
|
||||||
|
|
||||||
/* Run state machine with the same objects twice to test that it's allowed to
|
/* Run state machine with the same objects twice to test that it's allowed to
|
||||||
* reinitialize session and session_signer_data. */
|
* reinitialize session and session_signer_data. */
|
||||||
@ -618,17 +594,19 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
|
|||||||
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &combined_pk, &pre_session, pk, 2) == 1);
|
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &combined_pk, &pre_session, pk, 2) == 1);
|
||||||
CHECK(secp256k1_musig_session_initialize(ctx, &session[0], signers0, nonce_commitment[0], session_id[0], msg, &combined_pk, &pre_session, 2, 0, sk[0]) == 1);
|
CHECK(secp256k1_musig_session_initialize(ctx, &session[0], signers0, nonce_commitment[0], session_id[0], msg, &combined_pk, &pre_session, 2, 0, sk[0]) == 1);
|
||||||
CHECK(secp256k1_musig_session_initialize(ctx, &session[1], signers1, nonce_commitment[1], session_id[1], msg, &combined_pk, &pre_session, 2, 1, sk[1]) == 1);
|
CHECK(secp256k1_musig_session_initialize(ctx, &session[1], signers1, nonce_commitment[1], session_id[1], msg, &combined_pk, &pre_session, 2, 1, sk[1]) == 1);
|
||||||
|
/* Can't combine nonces unless we're through round 1 already */
|
||||||
|
ecount = 0;
|
||||||
|
CHECK(secp256k1_musig_session_combine_nonces(ctx_tmp, &session[0], signers0, 2, NULL, NULL) == 0);
|
||||||
|
CHECK(ecount == 1);
|
||||||
|
|
||||||
/* Set nonce commitments */
|
/* Set nonce commitments */
|
||||||
ncs[0] = nonce_commitment[0];
|
ncs[0] = nonce_commitment[0];
|
||||||
ncs[1] = nonce_commitment[1];
|
ncs[1] = nonce_commitment[1];
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 1);
|
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 1);
|
||||||
/* Changing a nonce commitment is not okay */
|
/* Calling the function again is not okay */
|
||||||
ncs[1] = (unsigned char*) "this isn't a nonce commitment...";
|
ecount = 0;
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 0);
|
CHECK(secp256k1_musig_session_get_public_nonce(ctx_tmp, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 0);
|
||||||
/* Repeating with the same nonce commitments is okay */
|
CHECK(ecount == 1);
|
||||||
ncs[1] = nonce_commitment[1];
|
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[0], signers0, &nonce[0], ncs, 2, NULL) == 1);
|
|
||||||
|
|
||||||
/* Get nonce for signer 1 */
|
/* Get nonce for signer 1 */
|
||||||
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[1], signers1, &nonce[1], ncs, 2, NULL) == 1);
|
CHECK(secp256k1_musig_session_get_public_nonce(ctx, &session[1], signers1, &nonce[1], ncs, 2, NULL) == 1);
|
||||||
@ -654,9 +632,16 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
|
|||||||
|
|
||||||
/* Partially sign */
|
/* Partially sign */
|
||||||
CHECK(secp256k1_musig_partial_sign(ctx, &session[0], &partial_sig[0]) == 1);
|
CHECK(secp256k1_musig_partial_sign(ctx, &session[0], &partial_sig[0]) == 1);
|
||||||
/* Can't verify or sign until nonce is combined */
|
/* Can't verify, sign or combine signatures until nonce is combined */
|
||||||
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[0], &partial_sig[0], &pk[0]) == 0);
|
ecount = 0;
|
||||||
CHECK(secp256k1_musig_partial_sign(ctx, &session[1], &partial_sig[1]) == 0);
|
CHECK(secp256k1_musig_partial_sig_verify(ctx_tmp, &session[1], &signers1[0], &partial_sig[0], &pk[0]) == 0);
|
||||||
|
CHECK(ecount == 1);
|
||||||
|
CHECK(secp256k1_musig_partial_sign(ctx_tmp, &session[1], &partial_sig[1]) == 0);
|
||||||
|
CHECK(ecount == 2);
|
||||||
|
memset(&partial_sig[1], 0, sizeof(partial_sig[1]));
|
||||||
|
CHECK(secp256k1_musig_partial_sig_combine(ctx_tmp, &session[1], sig, partial_sig, 2) == 0);
|
||||||
|
CHECK(ecount == 3);
|
||||||
|
|
||||||
CHECK(secp256k1_musig_session_combine_nonces(ctx, &session[1], signers1, 2, NULL, NULL) == 1);
|
CHECK(secp256k1_musig_session_combine_nonces(ctx, &session[1], signers1, 2, NULL, NULL) == 1);
|
||||||
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[0], &partial_sig[0], &pk[0]) == 1);
|
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[0], &partial_sig[0], &pk[0]) == 1);
|
||||||
/* messagehash should be the same as a session whose get_public_nonce was called
|
/* messagehash should be the same as a session whose get_public_nonce was called
|
||||||
@ -672,11 +657,8 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
|
|||||||
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[1], &partial_sig[0], &pk[1]) == 0);
|
CHECK(secp256k1_musig_partial_sig_verify(ctx, &session[1], &signers1[1], &partial_sig[0], &pk[1]) == 0);
|
||||||
/* Can't get the public nonce until msg is set */
|
/* Can't get the public nonce until msg is set */
|
||||||
musig_state_machine_late_msg_test(pk, &combined_pk, &pre_session, nonce_commitment[0], &nonce[0], sk[1], session_id[1], msg);
|
musig_state_machine_late_msg_test(pk, &combined_pk, &pre_session, nonce_commitment[0], &nonce[0], sk[1], session_id[1], msg);
|
||||||
|
|
||||||
/* Can't verify and combine partial sigs until nonces are combined */
|
|
||||||
CHECK(musig_state_machine_missing_combine_test(pk, &combined_pk, &pre_session, nonce_commitment[0], &nonce[0], &partial_sig[0], msg, sk[1], session_id[1], &partial_sig[1], 0) == 0);
|
|
||||||
CHECK(musig_state_machine_missing_combine_test(pk, &combined_pk, &pre_session, nonce_commitment[0], &nonce[0], &partial_sig[0], msg, sk[1], session_id[1], &partial_sig[1], 1) == 1);
|
|
||||||
}
|
}
|
||||||
|
secp256k1_context_destroy(ctx_tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
|
void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user