-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
musig2 wrappers over libsecp #31
Conversation
src/libmusig2.c
Outdated
@@ -193,46 +196,79 @@ void musig2_context_sig_free(musig2_context_sig *mcs) { | |||
musig2_context_free(&mcs->mc); | |||
} | |||
|
|||
int musig2_prepare_signer_to_register(musig2_context_sig *mcs, unsigned char *serialized_pubkey, unsigned char serialized_batch_list[][MUSIG2_PUBKEY_BYTES_COMPRESSED]){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is only used internally. It could be static.
src/libmusig2.c
Outdated
if (secp256k1_keypair_pub(mcs->mc.ctx, &temp_pk, &mcs->keypair)) | ||
secp256k1_ec_pubkey_serialize(mcs->mc.ctx, serialized_pubkey, &ser_size, &temp_pk, SECP256K1_EC_COMPRESSED ); | ||
else { | ||
musig2_context_sig_free(mcs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Freeing the context within the function might result in a double free, or in using a freed pointer. This should be handled externally, as we might want to continue with the same context if the serialisation failed
src/libmusig2.c
Outdated
if (secp256k1_keypair_pub(mcs->mc.ctx, &temp_pk, mcs->comm_list[i])) | ||
secp256k1_ec_pubkey_serialize(mcs->mc.ctx, serialized_batch_list[i], &ser_size, &temp_pk, SECP256K1_EC_COMPRESSED ); | ||
else { | ||
musig2_context_sig_free(mcs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
src/libmusig2.c
Outdated
if (!musig2_prepare_signer_to_register(mcs, serialized_pubkey, serialized_comm_list)){ | ||
musig2_context_sig_free(mcs); | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that what prepare_signer_to_register
really does is serialise the pubkey and batched commitments. What do you think of having a function serialise_shareable_context
, that takes as input mcs and the two pointers for the serialised data? In this way we explicitly distinguish both calls
src/libmusig2.h
Outdated
#define MUSIG2_PUBKEY_BYTES 32 // XONLY PUBLIC KEY BYTES | ||
#define MUSIG2_PUBKEY_BYTES_COMPRESSED 33 // COMPRESSED PUBLIC KEY BYTES | ||
#define MUSIG2_PUBKEY_BYTES_FULL 64 // FULL SIZE PUBLIC KEY BYTES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's counterintuitive that BYTES_COMPRESSED
is larger than BYTES
. I would find a different name to the former (maybe something to do with omit sign bit or something of the sort)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest that the serialisation is separated from the initialisation function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes look good. Have a look at my comments, and change what you consider, but other than that, happy to see this merged.
src/libmusig2.c
Outdated
if (!musig2_key_gen(mcs)) { | ||
musig2_context_sig_free(mcs); | ||
return 0; | ||
} | ||
|
||
/* Generate the batch commitments for given signer */ | ||
if (!musig2_batch_commitment(mcs)) | ||
if (!musig2_batch_commitment(mcs)) { | ||
return 0; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be consistent with freeing the context. Both errors are the same (=0), so the function caller will always react the same way for failures. This means that the outcome of both failures needs to be the same wrt freeing the context. Either we free the context in or out of the function, but we cannot do both.
|
||
int musig2_verify_musig2(unsigned char *signature, const unsigned char *msg, int msg_len, musig2_aggr_pubkey *aggr_pk){ | ||
int result; | ||
secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be confusing for someone reading the code in the future to see these two functions: musig2_prepare_verifier
and musig2_verify_musig2
, and see that in both we create a new context and destroy it. For sake of clarity, I would comment why we do this, and the design decision for not doing it in a single function.
src/libmusig2.c
Outdated
|
||
musig2_context_free(&verifier_context); | ||
} | ||
|
||
int musig2_verify_musig2(unsigned char *signature, const unsigned char *msg, int msg_len, musig2_aggr_pubkey *aggr_pk){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int musig2_verify_musig2(unsigned char *signature, const unsigned char *msg, int msg_len, musig2_aggr_pubkey *aggr_pk){ | |
int musig2_verify(unsigned char *signature, const unsigned char *msg, int msg_len, musig2_aggr_pubkey *aggr_pk){ |
#define MUSIG2_SCALAR_BYTES 32 // SCALAR BYTES | ||
#define MUSIG2_PARSIG_BYTES 32 // PARTIAL SIGNATURE BYTES | ||
#define MUSIG2_AGGR_PUBKEY_BYTES 32 // XONLY PUBLIC KEY BYTES | ||
#define MUSIG2_PUBKEY_BYTES_COMPRESSED 33 // COMPRESSED PUBLIC KEY BYTES | ||
#define MUSIG2_PUBKEY_BYTES_FULL 64 // FULL SIZE PUBLIC KEY BYTES | ||
#define MUSIG2_BYTES 64 // SCHNORR SIGNATURE BYTES | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced by this naming. But this is just a suggestion. You'll be the main maintainer of the lib, so you can make the final call. The following is my reasoning:
MUSIG2_PARSIG_BYTES
is a bit confusing, because we definemusig2_partial_signature
to be two values with a total of 64 bytes. This variable is really used to determine the size of the 'scalar part' of the partial signature.- I think I would remove the parsig bytes, and simply use
SCALAR_BYTES
andMUSIG2_BYTES
for referring to the size of the signatures.
Sorry, for the double comments. I'm using the code editor to review the PR and something clearly went wrong 😅 |
This PR aims to update the library so that the end users do not need to make calls from
secp256k1
as mentioned in #30. The following list provides the changes:Library functions are updated not to take any
secp256k1
parameters, includingsecp256k1_context
. Context creation is now handled in library functions.Defined constants renamed, i.e.,
SCALAR_BYTES
is changed toMUSIG2_SCALAR_BYTES
.A new type (
musig2_pubkey
) representing the x_only public key ofsecp256k1
is defined. MuSig2 library does not require full-size public keys; thus, instead of callingsecp256k1_xonly_pubkey
, users will callmusig2_pubkey
.The function
musig2_prepare_signer_to_register
is created. This functionmusig2_prepare_signer_to_register
,serialized_pk
(33-byte) andserialized_comm_list
, which is a list of 33-byte commitments withV * NR_MESSAGES
elements. So, after initialization, these return values can be directly used to register the signer (Collecting public keys and batch commitments.Verification of the final signature with
secp256k1_schnorrsig_verify
is implemented in the library functionmusig2_verify_musig2
.Note that the documentation and comments are not completed yet.
This closes #30.