musig: change pubkey_combine arg to array of pointers to pks

... instead of taking an array of pubkeys directly
This commit is contained in:
Jonas Nick 2021-05-07 15:26:33 +00:00
parent 08fa02d579
commit 56014e8ca0
4 changed files with 60 additions and 34 deletions

View File

@ -154,9 +154,9 @@ typedef struct {
* Out: combined_pk: the MuSig-combined xonly public key (cannot be NULL)
* pre_session: if non-NULL, pointer to a musig_pre_session struct to be used in
* `musig_session_init` or `musig_pubkey_tweak_add`.
* In: pubkeys: input array of public keys to combine. The order is important;
* a different order will result in a different combined public
* key (cannot be NULL)
* In: pubkeys: input array of pointers to public keys to combine. The order
* is important; a different order will result in a different
* combined public key (cannot be NULL)
* n_pubkeys: length of pubkeys array. Must be greater than 0.
*/
SECP256K1_API int secp256k1_musig_pubkey_combine(
@ -164,7 +164,7 @@ SECP256K1_API int secp256k1_musig_pubkey_combine(
secp256k1_scratch_space *scratch,
secp256k1_xonly_pubkey *combined_pk,
secp256k1_musig_pre_session *pre_session,
const secp256k1_xonly_pubkey *pubkeys,
const secp256k1_xonly_pubkey * const* pubkeys,
size_t n_pubkeys
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);

View File

@ -40,7 +40,7 @@ int create_keypair(const secp256k1_context* ctx, unsigned char *seckey, secp256k
}
/* Sign a message hash with the given key pairs and store the result in sig */
int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp256k1_xonly_pubkey* pubkeys, const unsigned char* msg32, unsigned char *sig64) {
int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp256k1_xonly_pubkey** pubkeys, const unsigned char* msg32, unsigned char *sig64) {
secp256k1_musig_session musig_session[N_SIGNERS];
unsigned char nonce_commitment[N_SIGNERS][32];
const unsigned char *nonce_commitment_ptr[N_SIGNERS];
@ -117,7 +117,7 @@ int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp25
* fine to first verify the combined sig, and only verify the individual
* sigs if it does not work.
*/
if (!secp256k1_musig_partial_sig_verify(ctx, &musig_session[i], &signer_data[i][j], &partial_sig[j], &pubkeys[j])) {
if (!secp256k1_musig_partial_sig_verify(ctx, &musig_session[i], &signer_data[i][j], &partial_sig[j], pubkeys[j])) {
return 0;
}
}
@ -130,6 +130,7 @@ int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp25
int i;
unsigned char seckeys[N_SIGNERS][32];
secp256k1_xonly_pubkey pubkeys[N_SIGNERS];
const secp256k1_xonly_pubkey *pubkeys_ptr[N_SIGNERS];
secp256k1_xonly_pubkey combined_pk;
unsigned char msg[32] = "this_could_be_the_hash_of_a_msg!";
unsigned char sig[64];
@ -142,16 +143,17 @@ int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp25
printf("FAILED\n");
return 1;
}
pubkeys_ptr[i] = &pubkeys[i];
}
printf("ok\n");
printf("Combining public keys...");
if (!secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, NULL, pubkeys, N_SIGNERS)) {
if (!secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, NULL, pubkeys_ptr, N_SIGNERS)) {
printf("FAILED\n");
return 1;
}
printf("ok\n");
printf("Signing message.........");
if (!sign(ctx, seckeys, pubkeys, msg, sig)) {
if (!sign(ctx, seckeys, pubkeys_ptr, msg, sig)) {
printf("FAILED\n");
return 1;
}

View File

@ -13,14 +13,14 @@
#include "hash.h"
/* Computes ell = SHA256(pk[0], ..., pk[np-1]) */
static int secp256k1_musig_compute_ell(const secp256k1_context *ctx, unsigned char *ell, const secp256k1_xonly_pubkey *pk, size_t np) {
static int secp256k1_musig_compute_ell(const secp256k1_context *ctx, unsigned char *ell, const secp256k1_xonly_pubkey * const* pk, size_t np) {
secp256k1_sha256 sha;
size_t i;
secp256k1_sha256_initialize(&sha);
for (i = 0; i < np; i++) {
unsigned char ser[32];
if (!secp256k1_xonly_pubkey_serialize(ctx, ser, &pk[i])) {
if (!secp256k1_xonly_pubkey_serialize(ctx, ser, pk[i])) {
return 0;
}
secp256k1_sha256_write(&sha, ser, 32);
@ -74,14 +74,14 @@ static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_musi
typedef struct {
const secp256k1_context *ctx;
unsigned char ell[32];
const secp256k1_xonly_pubkey *pks;
const secp256k1_xonly_pubkey * const* pks;
secp256k1_fe second_pk_x;
} secp256k1_musig_pubkey_combine_ecmult_data;
/* Callback for batch EC multiplication to compute ell_0*P0 + ell_1*P1 + ... */
static int secp256k1_musig_pubkey_combine_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) {
secp256k1_musig_pubkey_combine_ecmult_data *ctx = (secp256k1_musig_pubkey_combine_ecmult_data *) data;
if (!secp256k1_xonly_pubkey_load(ctx->ctx, pt, &ctx->pks[idx])) {
if (!secp256k1_xonly_pubkey_load(ctx->ctx, pt, ctx->pks[idx])) {
return 0;
}
secp256k1_musig_keyaggcoef_internal(sc, ctx->ell, &pt->x, &ctx->second_pk_x);
@ -98,7 +98,7 @@ static void secp256k1_musig_signers_init(secp256k1_musig_session_signer_data *si
static const uint64_t pre_session_magic = 0xf4adbbdf7c7dd304UL;
int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_xonly_pubkey *combined_pk, secp256k1_musig_pre_session *pre_session, const secp256k1_xonly_pubkey *pubkeys, size_t n_pubkeys) {
int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_xonly_pubkey *combined_pk, secp256k1_musig_pre_session *pre_session, const secp256k1_xonly_pubkey * const* pubkeys, size_t n_pubkeys) {
secp256k1_musig_pubkey_combine_ecmult_data ecmult_data;
secp256k1_gej pkj;
secp256k1_ge pkp;
@ -117,10 +117,10 @@ int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scrat
secp256k1_fe_set_int(&ecmult_data.second_pk_x, 0);
for (i = 1; i < n_pubkeys; i++) {
secp256k1_ge pt;
if (!secp256k1_xonly_pubkey_load(ctx, &pt, &pubkeys[i])) {
if (!secp256k1_xonly_pubkey_load(ctx, &pt, pubkeys[i])) {
return 0;
}
if (secp256k1_memcmp_var(&pubkeys[0], &pubkeys[i], sizeof(pubkeys[0])) != 0) {
if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) {
ecmult_data.second_pk_x = pt.x;
break;
}

View File

@ -30,6 +30,7 @@ void musig_simple_test(secp256k1_scratch_space *scratch) {
secp256k1_musig_pre_session pre_session;
unsigned char session_id[2][32];
secp256k1_xonly_pubkey pk[2];
const secp256k1_xonly_pubkey *pk_ptr[2];
const unsigned char *ncs[2];
unsigned char public_nonce[3][32];
secp256k1_musig_partial_signature partial_sig[2];
@ -41,10 +42,12 @@ void musig_simple_test(secp256k1_scratch_space *scratch) {
secp256k1_testrand256(sk[1]);
secp256k1_testrand256(msg);
pk_ptr[0] = &pk[0];
pk_ptr[1] = &pk[1];
CHECK(secp256k1_xonly_pubkey_create(&pk[0], sk[0]) == 1);
CHECK(secp256k1_xonly_pubkey_create(&pk[1], sk[1]) == 1);
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_ptr, 2) == 1);
CHECK(secp256k1_musig_session_init(ctx, &session[1], signer1, nonce_commitment[1], session_id[1], msg, &combined_pk, &pre_session, 2, sk[1]) == 1);
CHECK(secp256k1_musig_session_init(ctx, &session[0], signer0, nonce_commitment[0], session_id[0], msg, &combined_pk, &pre_session, 2, sk[0]) == 1);
@ -98,6 +101,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
secp256k1_musig_pre_session pre_session;
secp256k1_musig_pre_session pre_session_uninitialized;
secp256k1_xonly_pubkey pk[2];
const secp256k1_xonly_pubkey *pk_ptr[2];
unsigned char tweak[32];
unsigned char sec_adaptor[32];
@ -132,6 +136,8 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
secp256k1_testrand256(sec_adaptor);
secp256k1_testrand256(tweak);
pk_ptr[0] = &pk[0];
pk_ptr[1] = &pk[1];
CHECK(secp256k1_xonly_pubkey_create(&pk[0], sk[0]) == 1);
CHECK(secp256k1_xonly_pubkey_create(&pk[1], sk[1]) == 1);
CHECK(secp256k1_ec_pubkey_create(ctx, &adaptor, sec_adaptor) == 1);
@ -141,34 +147,34 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
/* Key combination */
ecount = 0;
CHECK(secp256k1_musig_pubkey_combine(none, scratch, &combined_pk, &pre_session, pk, 2) == 0);
CHECK(secp256k1_musig_pubkey_combine(none, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_musig_pubkey_combine(sign, scratch, &combined_pk, &pre_session, pk, 2) == 0);
CHECK(secp256k1_musig_pubkey_combine(sign, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(ecount == 2);
/* pubkey_combine does not require a scratch space */
CHECK(secp256k1_musig_pubkey_combine(vrfy, NULL, &combined_pk, &pre_session, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, NULL, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(ecount == 2);
/* A small scratch space works too, but will result in using an ineffecient algorithm */
scratch_small = secp256k1_scratch_space_create(ctx, 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch_small, &combined_pk, &pre_session, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch_small, &combined_pk, &pre_session, pk_ptr, 2) == 1);
secp256k1_scratch_space_destroy(ctx, scratch_small);
CHECK(ecount == 2);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, NULL, &pre_session, pk, 2) == 0);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, NULL, &pre_session, pk_ptr, 2) == 0);
CHECK(ecount == 3);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, NULL, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, NULL, pk_ptr, 2) == 1);
CHECK(ecount == 3);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, NULL, 2) == 0);
CHECK(ecount == 4);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk, 0) == 0);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 0) == 0);
CHECK(ecount == 5);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, NULL, 0) == 0);
CHECK(ecount == 6);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
/** Tweaking */
ecount = 0;
@ -517,6 +523,7 @@ void musig_state_machine_diff_signer_msghash_test(unsigned char *msghash, secp25
secp256k1_musig_session_signer_data signers_tmp[2];
unsigned char sk_dummy[32];
secp256k1_xonly_pubkey pks_tmp[2];
const secp256k1_xonly_pubkey *pks_tmp_ptr[2];
secp256k1_xonly_pubkey combined_pk_tmp;
secp256k1_musig_pre_session pre_session_tmp;
unsigned char nonce[32];
@ -525,7 +532,9 @@ void musig_state_machine_diff_signer_msghash_test(unsigned char *msghash, secp25
secp256k1_testrand256(sk_dummy);
pks_tmp[0] = pks[0];
CHECK(secp256k1_xonly_pubkey_create(&pks_tmp[1], sk_dummy) == 1);
CHECK(secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk_tmp, &pre_session_tmp, pks_tmp, 2) == 1);
pks_tmp_ptr[0] = &pks_tmp[0];
pks_tmp_ptr[1] = &pks_tmp[1];
CHECK(secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk_tmp, &pre_session_tmp, pks_tmp_ptr, 2) == 1);
CHECK(secp256k1_musig_session_init(ctx, &session_tmp, signers_tmp, nonce_commitment, session_id, msg, &combined_pk_tmp, &pre_session_tmp, 2, sk_dummy) == 1);
CHECK(secp256k1_musig_session_init(ctx, &session, signers, nonce_commitment, session_id, msg, combined_pk, pre_session, 2, sk) == 1);
@ -625,6 +634,7 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
unsigned char msg[32];
unsigned char sk[2][32];
secp256k1_xonly_pubkey pk[2];
const secp256k1_xonly_pubkey *pk_ptr[2];
secp256k1_xonly_pubkey combined_pk;
secp256k1_musig_pre_session pre_session;
unsigned char nonce[2][32];
@ -647,9 +657,11 @@ void musig_state_machine_tests(secp256k1_scratch_space *scratch) {
secp256k1_testrand256(sk[0]);
secp256k1_testrand256(sk[1]);
secp256k1_testrand256(msg);
pk_ptr[0] = &pk[0];
pk_ptr[1] = &pk[1];
CHECK(secp256k1_xonly_pubkey_create(&pk[0], sk[0]) == 1);
CHECK(secp256k1_xonly_pubkey_create(&pk[1], sk[1]) == 1);
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_ptr, 2) == 1);
CHECK(secp256k1_musig_session_init(ctx, &session[0], signers0, nonce_commitment[0], session_id[0], msg, &combined_pk, &pre_session, 2, sk[0]) == 1);
CHECK(secp256k1_musig_session_init(ctx, &session[1], signers1, nonce_commitment[1], session_id[1], msg, &combined_pk, &pre_session, 2, sk[1]) == 1);
/* Can't combine nonces unless we're through round 1 already */
@ -736,7 +748,9 @@ void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
unsigned char seckey_a[2][32];
unsigned char seckey_b[2][32];
secp256k1_xonly_pubkey pk_a[2];
const secp256k1_xonly_pubkey *pk_a_ptr[2];
secp256k1_xonly_pubkey pk_b[2];
const secp256k1_xonly_pubkey *pk_b_ptr[2];
secp256k1_musig_pre_session pre_session_a;
secp256k1_musig_pre_session pre_session_b;
secp256k1_xonly_pubkey combined_pk_a;
@ -765,14 +779,18 @@ void scriptless_atomic_swap(secp256k1_scratch_space *scratch) {
secp256k1_testrand256(seckey_b[1]);
secp256k1_testrand256(sec_adaptor);
pk_a_ptr[0] = &pk_a[0];
pk_a_ptr[1] = &pk_a[1];
pk_b_ptr[0] = &pk_b[0];
pk_b_ptr[1] = &pk_b[1];
CHECK(secp256k1_xonly_pubkey_create(&pk_a[0], seckey_a[0]));
CHECK(secp256k1_xonly_pubkey_create(&pk_a[1], seckey_a[1]));
CHECK(secp256k1_xonly_pubkey_create(&pk_b[0], seckey_b[0]));
CHECK(secp256k1_xonly_pubkey_create(&pk_b[1], seckey_b[1]));
CHECK(secp256k1_ec_pubkey_create(ctx, &pub_adaptor, sec_adaptor));
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &combined_pk_a, &pre_session_a, pk_a, 2));
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &combined_pk_b, &pre_session_b, pk_b, 2));
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &combined_pk_a, &pre_session_a, pk_a_ptr, 2));
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &combined_pk_b, &pre_session_b, pk_b_ptr, 2));
CHECK(secp256k1_musig_session_init(ctx, &musig_session_a[0], data_a, noncommit_a[0], seed, msg32_a, &combined_pk_a, &pre_session_a, 2, seckey_a[0]));
CHECK(secp256k1_musig_session_init(ctx, &musig_session_a[1], data_a, noncommit_a[1], seed, msg32_a, &combined_pk_a, &pre_session_a, 2, seckey_a[1]));
@ -909,6 +927,7 @@ void musig_tweak_test_helper(const secp256k1_xonly_pubkey* combined_pubkey, cons
void musig_tweak_test(secp256k1_scratch_space *scratch) {
unsigned char sk[2][32];
secp256k1_xonly_pubkey pk[2];
const secp256k1_xonly_pubkey *pk_ptr[2];
secp256k1_musig_pre_session pre_session_P;
secp256k1_musig_pre_session pre_session_Q;
secp256k1_xonly_pubkey P;
@ -927,9 +946,11 @@ void musig_tweak_test(secp256k1_scratch_space *scratch) {
secp256k1_testrand256(sk[1]);
secp256k1_testrand256(contract);
pk_ptr[0] = &pk[0];
pk_ptr[1] = &pk[1];
CHECK(secp256k1_xonly_pubkey_create(&pk[0], sk[0]) == 1);
CHECK(secp256k1_xonly_pubkey_create(&pk[1], sk[1]) == 1);
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &P, &pre_session_P, pk, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(ctx, scratch, &P, &pre_session_P, pk_ptr, 2) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, P_serialized, &P) == 1);
secp256k1_sha256_initialize(&sha);
@ -951,7 +972,8 @@ void musig_tweak_test(secp256k1_scratch_space *scratch) {
}
void musig_test_vectors_helper(unsigned char pk_ser[][32], int n_pks, const unsigned char *combined_pk_expected, int has_second_pk, int second_pk_idx) {
secp256k1_xonly_pubkey *pk = malloc(n_pks * sizeof(secp256k1_xonly_pubkey));
secp256k1_xonly_pubkey *pk = malloc(n_pks * sizeof(*pk));
const secp256k1_xonly_pubkey **pk_ptr = malloc(n_pks * sizeof(*pk_ptr));
secp256k1_xonly_pubkey combined_pk;
unsigned char combined_pk_ser[32];
secp256k1_musig_pre_session pre_session;
@ -960,9 +982,10 @@ void musig_test_vectors_helper(unsigned char pk_ser[][32], int n_pks, const unsi
for (i = 0; i < n_pks; i++) {
CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk[i], pk_ser[i]));
pk_ptr[i] = &pk[i];
}
CHECK(secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, &pre_session, pk, n_pks) == 1);
CHECK(secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, &pre_session, pk_ptr, n_pks) == 1);
CHECK(secp256k1_fe_set_b32(&second_pk_x, pre_session.second_pk));
CHECK(secp256k1_fe_is_zero(&second_pk_x) == !has_second_pk);
if (!secp256k1_fe_is_zero(&second_pk_x)) {
@ -982,6 +1005,7 @@ void musig_test_vectors_helper(unsigned char pk_ser[][32], int n_pks, const unsi
/* printf("};\n"); */
CHECK(secp256k1_memcmp_var(combined_pk_ser, combined_pk_expected, sizeof(combined_pk_ser)) == 0);
free(pk);
free(pk_ptr);
}
void musig_test_vectors(void) {