diff --git a/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h b/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h index 8fa0196..c7ff88e 100644 --- a/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h +++ b/jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h @@ -334,10 +334,10 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 /* * Class: fr_acinq_secp256k1_Secp256k1CFunctions * Method: secp256k1_frost_nonce_process - * Signature: (J[[B[B[B[B[[B[B[B)[B + * Signature: (J[[BI[B[B[B[[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1nonce_1process - (JNIEnv *, jclass, jlong, jobjectArray, jbyteArray, jbyteArray, jbyteArray, jobjectArray, jbyteArray, jbyteArray); + (JNIEnv *, jclass, jlong, jobjectArray, jint, jbyteArray, jbyteArray, jbyteArray, jobjectArray, jbyteArray, jbyteArray); /* * Class: fr_acinq_secp256k1_Secp256k1CFunctions diff --git a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c index c6d21a8..0ed2034 100644 --- a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c +++ b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c @@ -919,6 +919,17 @@ void free_nonces(secp256k1_musig_pubnonce **nonces, size_t count) free(nonces); } +void free_nonces(secp256k1_frost_pubnonce **nonces, size_t count) +{ + size_t i; + for (i = 0; i < count; i++) + { + if (nonces[i] != NULL) + free(nonces[i]); + } + free(nonces); +} + /* * Class: fr_acinq_secp256k1_Secp256k1CFunctions * Method: secp256k1_musig_nonce_agg @@ -1454,7 +1465,7 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 shares[i] = calloc(1, sizeof(secp256k1_frost_share)); jshare = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jshares, i); 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_shares(shares, count)); in32 = (*penv)->GetByteArrayElements(penv, jshare, 0); result = secp256k1_frost_share_parse(ctx, shares[i], (unsigned char *)in32); (*penv)->ReleaseByteArrayElements(penv, jshare, in32, 0); @@ -1638,8 +1649,13 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 &tweak_cache, &public_key ); + CHECKRESULT(!result, "secp256k1_frost_pubkey_tweak failed"); - // TODO: Return jbyte of the tweak_cache + size = sizeof(secp256k1_frost_tweak_cache); + jbyteArray jtweak_cache = (*penv)->NewByteArray(penv, size); + copy_bytes_to_java(penv, jtweak_cache, size, tweak_cache.data); + + return jtweak_cache; } /* @@ -1665,7 +1681,7 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 return NULL; size = (*penv)->GetArrayLength(penv, jtweak_cache); - CHECKRESULT(size != sizeof(secp256k1_frost_tweak_cache), "invalid keyagg cache size"); + CHECKRESULT(size != sizeof(secp256k1_frost_tweak_cache), "invalid tweak_cache size"); copy_bytes_from_java(penv, jtweak_cache, size, tweak_cache.data); if (jtweak32 == NULL) return NULL; @@ -1718,7 +1734,7 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 return NULL; size = (*penv)->GetArrayLength(penv, jtweak_cache); - CHECKRESULT(size != sizeof(secp256k1_frost_tweak_cache), "invalid keyagg cache size"); + CHECKRESULT(size != sizeof(secp256k1_frost_tweak_cache), "invalid tweak_cache size"); copy_bytes_from_java(penv, jtweak_cache, size, tweak_cache.data); if (jtweak32 == NULL) return NULL; @@ -1849,17 +1865,103 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2 /* * Class: fr_acinq_secp256k1_Secp256k1CFunctions * Method: secp256k1_frost_nonce_process - * Signature: (J[[B[B[B[B[[B[B[B)[B + * Signature: (J[[BI[B[B[B[[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1nonce_1process - (JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jpubnonces, jbyteArray jmsg32, jbyteArray jpubkey, jbyteArray jmy_id33, jobjectArray jids33, jbyteArray jtweak_cache, jbyteArray jadaptor) + (JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jpubnonces, jint n_pubnonces, jbyteArray jmsg32, jbyteArray jpubkey, jbyteArray jmy_id33, jobjectArray jids33, jbyteArray jtweak_cache, jbyteArray jadaptor) { secp256k1_context *ctx = (secp256k1_context *)jctx; secp256k1_frost_session session; - // TODO: Implement logic for the secp256k1_frost_nonce_process + secp256k1_frost_pubnonce **pubnonces; + jbyte *in66, *pub, *id33;; + unsigned char msg32[32]; + + secp256k1_xonly_pubkey public_key; + + const jbyte *ids33[jn_participants]; + + secp256k1_frost_tweak_cache tweak_cache; + secp256k1_pubkey adaptor; + + count = (*penv)->GetArrayLength(penv, jpubnonces); + CHECKRESULT(count <= 0, "public nonces count cannot be 0"); + + pubnonces = calloc(count, sizeof(secp256k1_frost_pubnonce *)); + + for (i = 0; i < count; i++) + { + pubnonces[i] = calloc(1, sizeof(secp256k1_frost_pubnonce)); + jnonce = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubnonces, i); + size = (*penv)->GetArrayLength(penv, jnonce); + CHECKRESULT1(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size", free_nonces(pubnonces, count)); + in66 = (*penv)->GetByteArrayElements(penv, jnonce, 0); + result = secp256k1_frost_pubnonce_parse(ctx, pubnonces[i], (unsigned char *)in66); + (*penv)->ReleaseByteArrayElements(penv, jnonce, in66, 0); + CHECKRESULT1(!result, "secp256k1_frost_pubnonce_parse failed", free_nonces(pubnonces, count)); + } + + if (jmsg32 != NULL) + { + size = (*penv)->GetArrayLength(penv, jmsg32); + CHECKRESULT(size != 32, "invalid message size"); + copy_bytes_from_java(penv, jmsg32, size, msg32); + } + + pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0); + result = secp256k1_xonly_pubkey_parse(ctx, &public_key, (unsigned char *)pub); + (*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0); + CHECKRESULT(!result, "secp256k1_xonly_pubkey_parse failed"); + + id33 = (*penv)->GetByteArrayElements(penv, jmy_id33, 0); + + // Copy over data from jids33 + if (jids33 != NULL) + { + size = (*penv)->GetArrayLength(penv, jids33); + CHECKRESULT(size != n_pubnonces, "invalid ids33 size"); + for (i = 0; i < n_pubnonces; i++) + { + jbyteArray id33 = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jids33, i); + // TODO: Check id33 size is 33... + ids33[i] = (*penv)->GetByteArrayElements(penv, id33, 0); + } + } + + + size = (*penv)->GetArrayLength(penv, jtweak_cache); + CHECKRESULT(size != sizeof(secp256k1_frost_tweak_cache), "invalid tweak_cache size"); + copy_bytes_from_java(penv, jtweak_cache, size, tweak_cache.data); + + if (jadaptor != NULL) + { + pub = (*penv)->GetByteArrayElements(penv, jadaptor, 0); + result = secp256k1_ec_pubkey_parse(ctx, &adaptor, (unsigned char *)pub, pubSize); + (*penv)->ReleaseByteArrayElements(penv, jadaptor, pub, 0); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + } + int result = secp256k1_frost_nonce_process( + ctx, + &session, + (const secp256k1_frost_pubnonce *const *)pubnonces, + n_pubnonces, + msg32, + &public_key, + id33, + ids33, + &tweak_cache, + jadaptor == NULL ? NULL : adaptor + ); + + CHECKRESULT(!result, "secp256k1_frost_nonce_process failed"); + + size = sizeof(secp256k1_frost_session); + jbyteArray jsession = (*penv)->NewByteArray(penv, size); + copy_bytes_to_java(penv, jsession, size, session.data); + + return jsession; } /* @@ -1890,18 +1992,18 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 if (jagg_share != NULL) { agg_share = calloc(1, sizeof(secp256k1_frost_share)); size = (*penv)->GetArrayLength(penv, jagg_share); - // 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 agg_share size", free_shares(shares, count)); in32 = (*penv)->GetByteArrayElements(penv, jagg_share, 0); result = secp256k1_frost_share_parse(ctx, agg_share, (unsigned char *)in32); (*penv)->ReleaseByteArrayElements(penv, jagg_share, in32, 0); - // TODO: CHECKRESULT1(!result, "secp256k1_frost_share_parse failed", free_shares(shares, count)); + CHECKRESULT1(!result, "secp256k1_frost_share_parse failed", free_shares(shares, count)); } CHECKRESULT((*penv)->GetArrayLength(penv, jsession) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, "invalid session size"); copy_bytes_from_java(penv, jsession, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, session.data); size = (*penv)->GetArrayLength(penv, jtweak_cache); - CHECKRESULT(size != sizeof(secp256k1_frost_tweak_cache), "invalid keyagg cache size"); + CHECKRESULT(size != sizeof(secp256k1_frost_tweak_cache), "invalid tweak_cache size"); copy_bytes_from_java(penv, jtweak_cache, size, tweak_cache.data); int result = secp256k1_frost_partial_sign( diff --git a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java index e98c498..230c7b4 100644 --- a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java +++ b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java @@ -331,7 +331,7 @@ public class Secp256k1CFunctions { * * @return session: pointer to a struct to store the session */ - public static native byte[] secp256k1_frost_nonce_process(long ctx, byte[][] pubnonces, byte[] msg32, byte[] publicKey, byte[] id33, byte[][] ids33, byte[] tweakCache, byte[] adaptor); + public static native byte[] secp256k1_frost_nonce_process(long ctx, byte[][] pubnonces, int n_pubnonces, byte[] msg32, byte[] publicKey, byte[] id33, byte[][] ids33, byte[] tweakCache, byte[] adaptor); /** * Produces a partial signature