Add support for musig2 (#93)
* Use Jonas Nick's musig2 branch * Reformat c code (no functional changes) * Implement musig2 * Add documentation to musig2 functions (#97) Usage of the Musig2 functions isn't intuitive at all, especially with the key aggregation cache and session data. It's important to provide accurate documentation to help users understand how to correctly produce musig2 signatures. We also change argument names to match Kotlin best practices instead of using the same argument names as C functions. * Add musig2 reference tests (no functional changes) --------- Co-authored-by: Bastien Teinturier <31281497+t-bast@users.noreply.github.com>
This commit is contained in:
@@ -29,12 +29,32 @@ public class Secp256k1CFunctions {
|
||||
public static final int SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION);
|
||||
public static final int SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION);
|
||||
|
||||
/**
|
||||
* A musig2 public nonce is simply two elliptic curve points.
|
||||
*/
|
||||
public static final int SECP256K1_MUSIG_PUBLIC_NONCE_SIZE = 66;
|
||||
|
||||
/**
|
||||
* A musig2 private nonce is basically two scalars, but should be treated as an opaque blob.
|
||||
*/
|
||||
public static final int SECP256K1_MUSIG_SECRET_NONCE_SIZE = 132;
|
||||
|
||||
/**
|
||||
* When aggregating public keys, we cache information in an opaque blob (must not be interpreted).
|
||||
*/
|
||||
public static final int SECP256K1_MUSIG_KEYAGG_CACHE_SIZE = 197;
|
||||
|
||||
/**
|
||||
* When creating partial signatures and aggregating them, session data is kept in an opaque blob (must not be interpreted).
|
||||
*/
|
||||
public static final int SECP256K1_MUSIG_SESSION_SIZE = 133;
|
||||
|
||||
public static native long secp256k1_context_create(int flags);
|
||||
|
||||
public static native void secp256k1_context_destroy(long ctx);
|
||||
|
||||
public static native int secp256k1_ec_seckey_verify(long ctx, byte[] seckey);
|
||||
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_parse(long ctx, byte[] pubkey);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_create(long ctx, byte[] seckey);
|
||||
@@ -68,4 +88,22 @@ public class Secp256k1CFunctions {
|
||||
public static native byte[] secp256k1_schnorrsig_sign(long ctx, byte[] msg, byte[] seckey, byte[] aux_rand32);
|
||||
|
||||
public static native int secp256k1_schnorrsig_verify(long ctx, byte[] sig, byte[] msg, byte[] pubkey);
|
||||
|
||||
public static native byte[] secp256k1_musig_nonce_gen(long ctx, byte[] session_id32, byte[] seckey, byte[] pubkey, byte[] msg32, byte[] keyagg_cache, byte[] extra_input32);
|
||||
|
||||
public static native byte[] secp256k1_musig_nonce_agg(long ctx, byte[][] nonces);
|
||||
|
||||
public static native byte[] secp256k1_musig_pubkey_agg(long ctx, byte[][] pubkeys, byte[] keyagg_cache);
|
||||
|
||||
public static native byte[] secp256k1_musig_pubkey_ec_tweak_add(long ctx, byte[] keyagg_cache, byte[] tweak32);
|
||||
|
||||
public static native byte[] secp256k1_musig_pubkey_xonly_tweak_add(long ctx, byte[] keyagg_cache, byte[] tweak32);
|
||||
|
||||
public static native byte[] secp256k1_musig_nonce_process(long ctx, byte[] aggnonce, byte[] msg32, byte[] keyagg_cache);
|
||||
|
||||
public static native byte[] secp256k1_musig_partial_sign(long ctx, byte[] secnonce, byte[] privkey, byte[] keyagg_cache, byte[] session);
|
||||
|
||||
public static native int secp256k1_musig_partial_sig_verify(long ctx, byte[] psig, byte[] pubnonce, byte[] pubkey, byte[] keyagg_cache, byte[] session);
|
||||
|
||||
public static native byte[] secp256k1_musig_partial_sig_agg(long ctx, byte[] session, byte[][] psigs);
|
||||
}
|
||||
|
||||
@@ -92,6 +92,42 @@ public object NativeSecp256k1 : Secp256k1 {
|
||||
return Secp256k1CFunctions.secp256k1_schnorrsig_sign(Secp256k1Context.getContext(), data, sec, auxrand32)
|
||||
}
|
||||
|
||||
override fun musigNonceGen(sessionId32: ByteArray, privkey: ByteArray?, aggpubkey: ByteArray, msg32: ByteArray?, keyaggCache: ByteArray?, extraInput32: ByteArray?): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_nonce_gen(Secp256k1Context.getContext(), sessionId32, privkey, aggpubkey, msg32, keyaggCache, extraInput32)
|
||||
}
|
||||
|
||||
override fun musigNonceAgg(pubnonces: Array<ByteArray>): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_nonce_agg(Secp256k1Context.getContext(), pubnonces)
|
||||
}
|
||||
|
||||
override fun musigPubkeyAgg(pubkeys: Array<ByteArray>, keyaggCache: ByteArray?): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_pubkey_agg(Secp256k1Context.getContext(), pubkeys, keyaggCache)
|
||||
}
|
||||
|
||||
override fun musigPubkeyTweakAdd(keyaggCache: ByteArray, tweak32: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_pubkey_ec_tweak_add(Secp256k1Context.getContext(), keyaggCache, tweak32)
|
||||
}
|
||||
|
||||
override fun musigPubkeyXonlyTweakAdd(keyaggCache: ByteArray, tweak32: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_pubkey_xonly_tweak_add(Secp256k1Context.getContext(), keyaggCache, tweak32)
|
||||
}
|
||||
|
||||
override fun musigNonceProcess(aggnonce: ByteArray, msg32: ByteArray, keyaggCache: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_nonce_process(Secp256k1Context.getContext(), aggnonce, msg32, keyaggCache)
|
||||
}
|
||||
|
||||
override fun musigPartialSign(secnonce: ByteArray, privkey: ByteArray, keyaggCache: ByteArray, session: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_partial_sign(Secp256k1Context.getContext(), secnonce, privkey, keyaggCache, session)
|
||||
}
|
||||
|
||||
override fun musigPartialSigVerify(psig: ByteArray, pubnonce: ByteArray, pubkey: ByteArray, keyaggCache: ByteArray, session: ByteArray): Int {
|
||||
return Secp256k1CFunctions.secp256k1_musig_partial_sig_verify(Secp256k1Context.getContext(), psig, pubnonce, pubkey, keyaggCache, session)
|
||||
}
|
||||
|
||||
override fun musigPartialSigAgg(session: ByteArray, psigs: Array<ByteArray>): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_musig_partial_sig_agg(Secp256k1Context.getContext(), session, psigs)
|
||||
}
|
||||
|
||||
override fun cleanup() {
|
||||
return Secp256k1CFunctions.secp256k1_context_destroy(Secp256k1Context.getContext())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user