From b4391813765be3c35af4d488dd0c0952d8ac40f2 Mon Sep 17 00:00:00 2001 From: kngako Date: Sun, 11 Aug 2024 03:43:30 +0200 Subject: [PATCH] JNI implementations --- .../fr_acinq_secp256k1_Secp256k1CFunctions.c | 306 ++++++++++++++++-- 1 file changed, 287 insertions(+), 19 deletions(-) diff --git a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c index 3e460f1..d73865b 100644 --- a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c +++ b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c @@ -1343,44 +1343,312 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_frost_shares_gen * Signature: (J[B[BII[[B)[[[B */ -JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1shares_1gen(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseed32, jint jthreshold, jint n_participants, jobjectArray jids33) +JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1shares_1gen(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseed32, jint jthreshold, jint jn_participants, jobjectArray jids33) { secp256k1_context *ctx = (secp256k1_context *)jctx; // This is what gets returned - secp256k1_frost_share shares[n_participants]; - secp256k1_pubkey vss_commitment[n_participants]; + secp256k1_frost_share shares[jn_participants]; + secp256k1_pubkey vss_commitment[jthreshold]; unsigned char pok64[64]; - // This is what gets passed - unsigned char seed32[32]; + size_t size; - const unsigned char *ids[n_participants]; + // This is what gets passed + jbyte *pubkeyBytes; + + unsigned char seed32[32]; + if (jseed32 != NULL) + { + size = (*penv)->GetArrayLength(penv, jseed32); + CHECKRESULT(size != 32, "invalid seed32 size"); + copy_bytes_from_java(penv, jseed32, size, seed32); + } + + const jbyte *ids33[jn_participants]; + // Copy over data from jids33 + if (jids33 != NULL) + { + size = (*penv)->GetArrayLength(penv, jids33); + CHECKRESULT(size != jn_participants, "invalid ids33 size"); + for (i = 0; i < jn_participants; i++) + { + jbyteArray id33 = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jids33, i); + // TODO: Check id33 size is 33... + ids33[i] = (*penv)->GetByteArrayElements(penv, id33, 0); + } + } int result = 0; - + result = secp256k1_frost_shares_gen( ctx, shares, vss_commitment, - jpok64, - jseed32, + pok64, + seed32, jthreshold, - n_participants, - jids33 + jn_participants, + ids33 ); + (*penv)->ReleaseByteArrayElements(penv, jseed32, seed32, 0); CHECKRESULT(!result, "secp256k1_frost_shares_gen failed"); - jobjectArray output = (*penv)->NewObjectArray(penv, 3, jbyteArray, NULL); + jbyte* jpok64; - jnonce = (*penv)->NewByteArray(penv, sizeof(shares)); - nonce_ptr = (*penv)->GetByteArrayElements(penv, jnonce, 0); - memcpy(nonce_ptr, nonce, sizeof(nonce)); - (*penv)->ReleaseByteArrayElements(penv, jnonce, nonce_ptr, 0); + jobjectArray output = (*penv)->NewObjectArray(penv, 3, jobjectArray, NULL); - output[0]; - output[1]; - output[2]; + output[0] = (*penv)->NewObjectArray(penv, jn_participants, jbyteArray, NULL); + output[1] = (*penv)->NewObjectArray(penv, jthreshold, jbyteArray, NULL); + output[2] = (*penv)->NewObjectArray(penv, 1, jbyteArray, NULL); + // TODO: Copy over the required data... return output; +} + +void free_shares(secp256k1_frost_share **shares, size_t count) +{ + size_t i; + for (i = 0; i < count; i++) + { + if (shares[i] != NULL) + free(shares[i]); + } + free(shares); +} + + +/* + * Class: fr_acinq_secp256k1_Secp256k1CFunctions + * Method: secp256k1_frost_share_agg + * Signature: (J[[B[[[BII[B)[[B + */ +JNIEXPORT jobjectArray 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; + + secp256k1_frost_share aggregate_share; + jbyteArray jaggregate_share; + secp256k1_xonly_pubkey aggregate_public_key; + jbyteArray jaggregate_public_key; + + const secp256k1_frost_share **shares; + jbyteArray jshare; + jbyte *in32; + + secp256k1_xonly_pubkey **vss_commitments; + jbyteArray jvss_commitment; + jbyte *pub; + + jbyte *id33; + + size_t size, count; + + count = (*penv)->GetArrayLength(penv, jnonces); + CHECKRESULT(count != jtotalShareCount, "jshares count should be total share count."); + shares = calloc(count, sizeof(secp256k1_frost_share*)); + + for (i = 0; i < count; i++) + { + 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)); + in32 = (*penv)->GetByteArrayElements(penv, jshare, 0); + result = secp256k1_frost_share_parse(ctx, shares[i], (unsigned char *)in32); + (*penv)->ReleaseByteArrayElements(penv, jshare, in32, 0); + CHECKRESULT1(!result, "secp256k1_frost_share_parse failed", free_shares(shares, count)); + } + + count = (*penv)->GetArrayLength(penv, jvss_commitments); + vss_commitments = calloc(count, sizeof(secp256k1_pubkey *)); + + for (i = 0; i < count; i++) + { + vss_commitments[i] = calloc(1, sizeof(secp256k1_pubkey)); + jvss_commitment = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jvss_commitments, i); + size = (*penv)->GetArrayLength(penv, jvss_commitment); + CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, count)); + pub = (*penv)->GetByteArrayElements(penv, jvss_commitment, 0); + result = secp256k1_ec_pubkey_parse(ctx, vss_commitments[i], (unsigned char *)pub, size); + (*penv)->ReleaseByteArrayElements(penv, jvss_commitment, pub, 0); + CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(vss_commitments, count)); + } + + id33 = (*penv)->GetByteArrayElements(penv, jid33, 0); + + + int result = 0; + + result = secp256k1_frost_share_agg( + ctx, + &aggregate_share, + &aggregate_public_key, + shares, + vss_commitments, + jtotalShareCount, + jthreshold, + (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); + 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); + CHECKRESULT(!result, "secp256k1_xonly_pubkey_serialize failed"); + + return output; +} + +/* + * Class: fr_acinq_secp256k1_Secp256k1CFunctions + * Method: secp256k1_frost_share_verify + * Signature: (JI[B[B[[B)I + */ +JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1share_1verify + (JNIEnv *penv, jclass clazz, jlong jctx, jint jthreshold, jbyteArray jid33, jbyteArray jshare, jobjectArray jvss_commitment) +{ + secp256k1_context *ctx = (secp256k1_context *)jctx; + + secp256k1_frost_share share; + jbyte *in32; + + jbyte *id33; + + secp256k1_xonly_pubkey *vss_commitment; + jbyte *jpub; + + 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)); + 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)); + + id33 = (*penv)->GetByteArrayElements(penv, jid33, 0); + + vss_commitment = calloc(1, sizeof(secp256k1_pubkey)); + jpub = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jvss_commitment, i); + size = (*penv)->GetArrayLength(penv, jpub); + CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, count)); + jpub = (*penv)->GetByteArrayElements(penv, jpub, 0); + result = secp256k1_ec_pubkey_parse(ctx, vss_commitment, (unsigned char *)jpub, size); + (*penv)->ReleaseByteArrayElements(penv, jpub, jpub, 0); + CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free(vss_commitment)); + + int result = secp256k1_frost_share_verify( + ctx, + jthreshold, + (unsigned char *)id33, + share, + vss_commitment + ); + + return result; +} + +/* + * Class: fr_acinq_secp256k1_Secp256k1CFunctions + * Method: secp256k1_frost_compute_pubshare + * Signature: (JI[B[[[BI)[B + */ +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1compute_1pubshare + (JNIEnv *penv, jclass clazz, jlong jctx, jint jthreshold, jbyteArray jid33, jobjectArray jvss_commitments, jint jtotalSignersCount) +{ + secp256k1_context *ctx = (secp256k1_context *)jctx; + + secp256k1_pubkey pubshare; + + jbyte *id33; + + secp256k1_xonly_pubkey **vss_commitments; + jbyteArray jvss_commitment; + jbyte *jpubkey; + + id33 = (*penv)->GetByteArrayElements(penv, jid33, 0); + + + count = (*penv)->GetArrayLength(penv, jvss_commitments); + vss_commitments = calloc(count, sizeof(secp256k1_pubkey *)); + + for (i = 0; i < count; i++) + { + vss_commitments[i] = calloc(1, sizeof(secp256k1_pubkey)); + jvss_commitment = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jvss_commitments, i); + size = (*penv)->GetArrayLength(penv, jvss_commitment); + CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, count)); + jpubkey = (*penv)->GetByteArrayElements(penv, jvss_commitment, 0); + result = secp256k1_ec_pubkey_parse(ctx, vss_commitments[i], (unsigned char *)jpub, size); + (*penv)->ReleaseByteArrayElements(penv, jvss_commitment, jpub, 0); + CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(vss_commitments, count)); + } + + int result = secp256k1_frost_compute_pubshare( + ctx, + &pubshare, + jthreshold, + (unsigned char *)id33 + vss_commitments, + jtotalSignersCount + ); + + jpubkey = (*penv)->NewByteArray(penv, 65); + jbyte *jpubkeyBytes = (*penv)->GetByteArrayElements(penv, jpubkey, 0); + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)jpubkeyBytes, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + (*penv)->ReleaseByteArrayElements(penv, jpubkey, jpubkeyBytes, 0); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + return jpubkey; +} + +/* + * Class: fr_acinq_secp256k1_Secp256k1CFunctions + * Method: secp256k1_frost_pubkey_tweak + * Signature: (J[B)[B + */ +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1pubkey_1tweak + (JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpublicKey) +{ + secp256k1_context *ctx = (secp256k1_context *)jctx; + + secp256k1_frost_tweak_cache tweak_cache; + secp256k1_xonly_pubkey public_key; + jbyte *pub; + + pub = (*penv)->GetByteArrayElements(penv, jpublicKey, 0); + result = secp256k1_xonly_pubkey_parse(ctx, &public_key, (unsigned char *)pub); + (*penv)->ReleaseByteArrayElements(penv, jpublicKey, pub, 0); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + int result = secp256k1_frost_pubkey_tweak( + ctx, + &tweak_cache, + &public_key + ); + + // TODO: Return jbyte of the tweak_cache +} + +/* + * Class: fr_acinq_secp256k1_Secp256k1CFunctions + * Method: secp256k1_frost_pubkey_ec_tweak_add + * Signature: (J[B[B)[B + */ +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1pubkey_1ec_1tweak_1add + (JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray, jbyteArray) +{ + // TODO: Implement secp256k1_frost_pubkey_ec_tweak_add } \ No newline at end of file