diff --git a/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h b/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h index c7ff88e..6268c13 100644 --- a/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h +++ b/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h @@ -278,9 +278,9 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 /* * Class: fr_acinq_secp256k1_Secp256k1CFunctions * Method: secp256k1_frost_share_agg - * Signature: (J[[B[[[BII[B)[[B + * Signature: (J[[B[[[BII[B)[B */ -JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1share_1agg +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1share_1agg (JNIEnv *, jclass, jlong, jobjectArray, jobjectArray, jint, jint, jbyteArray); /* @@ -318,17 +318,17 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 /* * Class: fr_acinq_secp256k1_Secp256k1CFunctions * Method: secp256k1_frost_pubkey_xonly_tweak_add - * Signature: (J[B[B)[[B + * Signature: (J[B[B)[B */ -JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1pubkey_1xonly_1tweak_1add +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1pubkey_1xonly_1tweak_1add (JNIEnv *, jclass, jlong, jbyteArray, jbyteArray); /* * Class: fr_acinq_secp256k1_Secp256k1CFunctions * Method: secp256k1_frost_nonce_gen - * Signature: (J[B[B[B[B[B)[[B + * Signature: (J[B[B[B[B[B)[B */ -JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1nonce_1gen +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1nonce_1gen (JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray); /* diff --git a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c index b25a8f7..98e6a6e 100644 --- a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c +++ b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c @@ -1440,7 +1440,7 @@ void free_shares(secp256k1_frost_share **shares, size_t count) * Method: secp256k1_frost_share_agg * Signature: (J[[B[[[BII[B)[[B */ -JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1share_1agg +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1share_1agg (JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jshares, jobjectArray jvss_commitments, jint jtotalShareCount, jint jthreshold, jbyteArray jid33) { secp256k1_context *ctx = (secp256k1_context *)jctx; @@ -1462,6 +1462,10 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 size_t size, count; + jbyteArray jresult; + jbyte *result_ptr = NULL; + unsigned char result_array[32 + 32]; // TODO: Put correct pubnonce + if (jctx == 0) return NULL; @@ -1511,7 +1515,6 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 id33 = (*penv)->GetByteArrayElements(penv, jid33, 0); - int result = 0; result = secp256k1_frost_share_agg( @@ -1525,24 +1528,18 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 (unsigned char *)id33 ); - jobjectArray output = (*penv)->NewObjectArray(penv, 2, jbyteArray, NULL); - - jaggregate_share = (*penv)->NewByteArray(penv, 64); - copy_bytes_to_java(penv, jaggregate_share, 64, aggregate_share); - - output[0] = (*penv)->NewByteArray(penv, 32); - pub = (*penv)->GetByteArrayElements(penv, output[0], 0); - result = secp256k1_frost_share_serialize(ctx, (unsigned char *)pub, &aggregate_share); - (*penv)->ReleaseByteArrayElements(penv, output[0], pub, 0); + result = secp256k1_frost_share_serialize(ctx, result_array, &aggregate_share); CHECKRESULT(!result, "secp256k1_frost_share_serialize failed"); - output[1] = (*penv)->NewByteArray(penv, 32); - pub = (*penv)->GetByteArrayElements(penv, output[1], 0); - result = secp256k1_xonly_pubkey_serialize(ctx, (unsigned char *)pub, &aggregate_public_key); - (*penv)->ReleaseByteArrayElements(penv, output[1], pub, 0); + result = secp256k1_xonly_pubkey_serialize(ctx, result_array + 32, &aggregate_public_key); CHECKRESULT(!result, "secp256k1_xonly_pubkey_serialize failed"); - return output; + jresult = (*penv)->NewByteArray(penv, sizeof(result_array)); + result_ptr = (*penv)->GetByteArrayElements(penv, jresult, 0); + memcpy(result_ptr, result_array, sizeof(result_array)); + (*penv)->ReleaseByteArrayElements(penv, jresult, result_ptr, 0); + + return jresult; } /* @@ -1581,11 +1578,11 @@ JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1fr share = calloc(1, sizeof(secp256k1_frost_share)); size = (*penv)->GetArrayLength(penv, jshare); -// TODO: CHECKRESULT1(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size", free_nonces(pubnonces, count)); + CHECKRESULT1(size != sizeof(secp256k1_frost_share), "invalid share size", free(&share)); in32 = (*penv)->GetByteArrayElements(penv, jshare, 0); result = secp256k1_frost_share_parse(ctx, share, (unsigned char *)in32); (*penv)->ReleaseByteArrayElements(penv, jshare, in32, 0); -// TODO: CHECKRESULT1(!result, "secp256k1_frost_share_parse failed", free_shares(shares, count)); + CHECKRESULT1(!result, "secp256k1_frost_share_parse failed", free(&share)); id33 = (*penv)->GetByteArrayElements(penv, jid33, 0); @@ -1779,7 +1776,7 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_frost_pubkey_xonly_tweak_add * Signature: (J[B[B)[[B */ -JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1pubkey_1xonly_1tweak_1add +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1pubkey_1xonly_1tweak_1add (JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jtweak_cache, jbyteArray jtweak32) { secp256k1_context *ctx = (secp256k1_context *)jctx; @@ -1808,14 +1805,20 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 CHECKRESULT((*penv)->GetArrayLength(penv, jtweak32) != 32, "tweak must be 32 bytes"); tweak32 = (*penv)->GetByteArrayElements(penv, jtweak32, 0); - int result = secp256k1_frost_pubkey_ec_tweak_add( + int result = secp256k1_frost_pubkey_xonly_tweak_add( ctx, - pubkey, + &pubkey, &tweak_cache, &public_key ); + (*penv)->ReleaseByteArrayElements(penv, jtweak32, tweak32, 0); - CHECKRESULT(!result, "secp256k1_frost_pubkey_ec_tweak_add failed"); + CHECKRESULT(!result, "secp256k1_frost_pubkey_xonly_tweak_add failed"); + + jbyteArray jresult; + jbyte *result_ptr = NULL; + unsigned char result_array[32 + sizeof(secp256k1_frost_tweak_cache)]; // TODO: Put correct pubnonce + jpubkey = (*penv)->NewByteArray(penv, 65); pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0); @@ -1825,7 +1828,7 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); pub = (*penv)->GetByteArrayElements(penv, jtweak_cache, 0); - memcpy(pub, tweak_cache.data, sizeof(secp256k1_musig_keyagg_cache)); + memcpy(pub, tweak_cache.data, sizeof(secp256k1_frost_tweak_cache)); (*penv)->ReleaseByteArrayElements(penv, jtweak_cache, pub, 0); return jpubkey; @@ -1836,7 +1839,7 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 * Method: secp256k1_frost_nonce_gen * Signature: (J[B[B[B[B[B)[[B */ -JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1nonce_1gen +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1nonce_1gen (JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsession_id32, jbyteArray jshare, jbyteArray jmsg32, jbyteArray jpubkey, jbyteArray jextra_input32) { secp256k1_context *ctx = (secp256k1_context *)jctx; @@ -1856,6 +1859,10 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 secp256k1_musig_keyagg_cache keyaggcache; unsigned char extra_input32[32]; + jbyteArray jnonce; + jbyte *nonce_ptr = NULL; + unsigned char nonce[sizeof(secp256k1_frost_secnonce) + sizeof(secp256k1_frost_pubnonce)]; // TODO: Put correct pubnonce + size_t size, count; if (jctx == 0) @@ -1915,18 +1922,17 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 ); CHECKRESULT(!result, "secp256k1_frost_nonce_gen failed"); - // TODO: copy nonce result... - // memcpy(nonce, secnonce.data, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE); - // result = secp256k1_musig_pubnonce_serialize(ctx, nonce + fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE, &pubnonce); - // CHECKRESULT(!result, "secp256k1_musig_pubnonce_serialize failed"); - // - // jnonce = (*penv)->NewByteArray(penv, sizeof(nonce)); - // nonce_ptr = (*penv)->GetByteArrayElements(penv, jnonce, 0); - // memcpy(nonce_ptr, nonce, sizeof(nonce)); - // (*penv)->ReleaseByteArrayElements(penv, jnonce, nonce_ptr, 0); - // - // return jnonce; + memcpy(nonce, secnonce.data, sizeof(secp256k1_frost_secnonce)); + result = secp256k1_frost_pubnonce_serialize(ctx, nonce + sizeof(secp256k1_frost_secnonce), &pubnonce); + CHECKRESULT(!result, "secp256k1_frost_pubnonce_serialize failed"); + + jnonce = (*penv)->NewByteArray(penv, sizeof(nonce)); + nonce_ptr = (*penv)->GetByteArrayElements(penv, jnonce, 0); + memcpy(nonce_ptr, nonce, sizeof(nonce)); + (*penv)->ReleaseByteArrayElements(penv, jnonce, nonce_ptr, 0); + + return jnonce; } /* diff --git a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java index 230c7b4..6bb910d 100644 --- a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java +++ b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java @@ -161,7 +161,7 @@ public class Secp256k1CFunctions { * [0] agg_share: the aggregated share * [1] agg_pk: the aggregated x-only public key */ - public static native byte[][] secp256k1_frost_share_agg(long ctx, byte[][] shares, byte[][][] vss_commitments, int totalShareCount, int threshold, byte[] id33); + public static native byte[] secp256k1_frost_share_agg(long ctx, byte[][] shares, byte[][][] vss_commitments, int totalShareCount, int threshold, byte[] id33); /** * Verifies a share received during a key generation session @@ -269,7 +269,7 @@ public class Secp256k1CFunctions { * function returns 0. If you do not need it, this arg can be NULL. * [1] tweak_cache: pointer to a `frost_tweak_cache` struct initialized by `frost_pubkey_tweak` */ - public static native byte[][] secp256k1_frost_pubkey_xonly_tweak_add(long ctx, byte[] tweakCache, byte[] tweak32); + public static native byte[] secp256k1_frost_pubkey_xonly_tweak_add(long ctx, byte[] tweakCache, byte[] tweak32); /** * Starts a signing session by generating a nonce @@ -310,7 +310,7 @@ public class Secp256k1CFunctions { * [0] secnonce: pointer to a structure to store the secret nonce * [1] pubnonce: pointer to a structure to store the public nonce */ - public static native byte[][] secp256k1_frost_nonce_gen(long ctx, byte[] sessionId32, byte[] share, byte[] msg32, byte[] publicKey, byte[] extraInput32); + public static native byte[] secp256k1_frost_nonce_gen(long ctx, byte[] sessionId32, byte[] share, byte[] msg32, byte[] publicKey, byte[] extraInput32); /** * Takes the public nonces of all signers and computes a session that is diff --git a/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt b/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt index d78dd1e..8bba854 100644 --- a/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt +++ b/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt @@ -166,8 +166,8 @@ public object NativeSecp256k1 : Secp256k1 { id33 ) return Pair( - result[0], // agg_share - result[1] // agg_pk + result.take(Secp256k1.FROST_SERIALIZED_SHARE_SIZE).toByteArray(), // agg_share + result.takeLast(Secp256k1.SERIALIZED_X_ONLY_PUBKEY_SIZE).toByteArray() // agg_pk ) } @@ -216,17 +216,12 @@ public object NativeSecp256k1 : Secp256k1 { ) } - override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair { - val result = Secp256k1CFunctions.secp256k1_frost_pubkey_xonly_tweak_add( + override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): ByteArray? { + return Secp256k1CFunctions.secp256k1_frost_pubkey_xonly_tweak_add( Secp256k1Context.getContext(), tweakCache, tweak32 ) - - return Pair( - result[0], // output_pubkey - result[1] // tweak_cache - ) } override fun frostNonceGen( @@ -246,8 +241,8 @@ public object NativeSecp256k1 : Secp256k1 { ) return Pair( - result[0], // secnonce - result[1] // pubnonce + result.take(Secp256k1.FROST_SECNONCE_SIZE).toByteArray(), // secnonce + result.takeLast(Secp256k1.FROST_SERIALIZED_PUBNONCE_SIZE).toByteArray() // pubnonce ) } diff --git a/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt b/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt index 56c71d3..898dbce 100644 --- a/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt +++ b/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt @@ -293,7 +293,7 @@ public interface Secp256k1 { public fun frostPublicKeyEcTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): ByteArray? - public fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair + public fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): ByteArray? public fun frostNonceGen(sessionId32: ByteArray, share: ByteArray?, msg32: ByteArray?, publicKey: ByteArray?, extraInput32: ByteArray?): Pair @@ -320,6 +320,7 @@ public interface Secp256k1 { // @formatter:off public const val X_ONLY_PUBKEY_SIZE: Int = 64 + public const val SERIALIZED_X_ONLY_PUBKEY_SIZE: Int = 32 public const val MUSIG2_SECRET_NONCE_SIZE: Int = 132 public const val MUSIG2_PUBLIC_NONCE_SIZE: Int = 66 @@ -334,8 +335,8 @@ public interface Secp256k1 { public const val FROST_SECNONCE_SIZE: Int = 69 public const val FROST_PUBNONCE_SIZE: Int = 133 public const val FROST_SERIALIZED_PARTIAL_SIGNATURE_SIZE: Int = 33 - public const val FROST_SERIALIZED_SHARE_SIZE: Int = 33 - public const val FROST_SERIALIZED_PUBNONCE_SIZE: Int = 67 + public const val FROST_SERIALIZED_SHARE_SIZE: Int = 32 + public const val FROST_SERIALIZED_PUBNONCE_SIZE: Int = 66 // @formatter:on } } diff --git a/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt b/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt index c8abc1b..d56483d 100644 --- a/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt +++ b/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt @@ -696,7 +696,7 @@ public object Secp256k1Native : Secp256k1 { return natOutput } - override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair { + override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): ByteArray? { require(tweakCache.size == Secp256k1.FROST_TWEAK_CACHE_SIZE) require(tweak32.size == 32) @@ -713,10 +713,7 @@ public object Secp256k1Native : Secp256k1 { tweak32 = toNat(tweak32) ) - return Pair( - serializePubkey(nPublicKey), - serializeFrostTweakCache(nTweakCache) - ) + return serializePubkey(nPublicKey) } }