Skip to content

Commit 5e7d1a5

Browse files
committed
JNI: Use GetByteArrayRegion/SetByteArrayRegion
1 parent 57ca02c commit 5e7d1a5

File tree

2 files changed

+62
-23
lines changed

2 files changed

+62
-23
lines changed

jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ void free_nonces(secp256k1_musig_pubnonce **nonces, size_t count)
994994
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1agg(JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jnonces)
995995
{
996996
secp256k1_context *ctx = (secp256k1_context *)jctx;
997-
jbyte *in66;
997+
jbyte in66[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE];
998998
secp256k1_musig_pubnonce **pubnonces;
999999
secp256k1_musig_aggnonce combined;
10001000
jbyteArray jnonce;
@@ -1009,29 +1009,32 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
10091009

10101010
count = (*penv)->GetArrayLength(penv, jnonces);
10111011
CHECKRESULT(count <= 0, "public nonces count cannot be 0");
1012+
for (i = 0; i < count; i++)
1013+
{
1014+
jnonce = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jnonces, i);
1015+
size = (*penv)->GetArrayLength(penv, jnonce);
1016+
CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size");
1017+
}
10121018

10131019
pubnonces = calloc(count, sizeof(secp256k1_musig_pubnonce *));
10141020

10151021
for (i = 0; i < count; i++)
10161022
{
10171023
pubnonces[i] = calloc(1, sizeof(secp256k1_musig_pubnonce));
10181024
jnonce = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jnonces, i);
1019-
size = (*penv)->GetArrayLength(penv, jnonce);
1020-
CHECKRESULT1(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size", free_nonces(pubnonces, count));
1021-
in66 = (*penv)->GetByteArrayElements(penv, jnonce, 0);
1025+
size = fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE;
1026+
(*penv)->GetBooleanArrayRegion(penv, jnonce, 0, size, in66);
10221027
result = secp256k1_musig_pubnonce_parse(ctx, pubnonces[i], (unsigned char *)in66);
1023-
(*penv)->ReleaseByteArrayElements(penv, jnonce, in66, 0);
1024-
CHECKRESULT1(!result, "secp256k1_musig_pubnonce_parse failed", free_nonces(pubnonces, count));
1028+
CHECKRESULT1(!result, "secp256k1_musig_pubnonce_parse failed", free_nonces(pubnonces, i));
10251029
}
10261030
result = secp256k1_musig_nonce_agg(ctx, &combined, (const secp256k1_musig_pubnonce *const *)pubnonces, count);
10271031
free_nonces(pubnonces, count);
10281032
CHECKRESULT(!result, "secp256k1_musig_nonce_agg failed");
10291033

1030-
jnonce = (*penv)->NewByteArray(penv, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE);
1031-
in66 = (*penv)->GetByteArrayElements(penv, jnonce, 0);
10321034
result = secp256k1_musig_aggnonce_serialize(ctx, (unsigned char *)in66, &combined);
1033-
(*penv)->ReleaseByteArrayElements(penv, jnonce, in66, 0);
10341035
CHECKRESULT(!result, "secp256k1_musig_aggnonce_serialize failed");
1036+
jnonce = (*penv)->NewByteArray(penv, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE);
1037+
(*penv)->SetByteArrayRegion(penv, jnonce, 0, size, in66);
10351038
return jnonce;
10361039
}
10371040

@@ -1043,7 +1046,7 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
10431046
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1agg(JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jpubkeys, jbyteArray jkeyaggcache)
10441047
{
10451048
secp256k1_context *ctx = (secp256k1_context *)jctx;
1046-
jbyte *pub;
1049+
jbyte pub[65];
10471050
secp256k1_pubkey **pubkeys;
10481051
secp256k1_xonly_pubkey combined;
10491052
secp256k1_musig_keyagg_cache keyaggcache;
@@ -1056,7 +1059,14 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
10561059
return NULL;
10571060
if (jpubkeys == NULL)
10581061
return NULL;
1059-
CHECKRESULT((*penv)->GetArrayLength(penv, jpubkeys) <= 0, "pubkeys count cannot be 0");
1062+
count = (*penv)->GetArrayLength(penv, jpubkeys);
1063+
CHECKRESULT(count <= 0, "pubkeys count cannot be 0");
1064+
for (i = 0; i < count; i++)
1065+
{
1066+
jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i);
1067+
size = (*penv)->GetArrayLength(penv, jpubkey);
1068+
CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, count));
1069+
}
10601070

10611071
if (jkeyaggcache != NULL)
10621072
{
@@ -1065,35 +1075,29 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
10651075
copy_bytes_from_java(penv, jkeyaggcache, size, keyaggcache.data);
10661076
}
10671077

1068-
count = (*penv)->GetArrayLength(penv, jpubkeys);
10691078
pubkeys = calloc(count, sizeof(secp256k1_pubkey *));
10701079

10711080
for (i = 0; i < count; i++)
10721081
{
10731082
pubkeys[i] = calloc(1, sizeof(secp256k1_pubkey));
10741083
jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i);
10751084
size = (*penv)->GetArrayLength(penv, jpubkey);
1076-
CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, count));
1077-
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
1085+
(*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub);
10781086
result = secp256k1_ec_pubkey_parse(ctx, pubkeys[i], (unsigned char *)pub, size);
1079-
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
1080-
CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(pubkeys, count));
1087+
CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(pubkeys, i));
10811088
}
10821089
result = secp256k1_musig_pubkey_agg(ctx, &combined, jkeyaggcache == NULL ? NULL : &keyaggcache, (const secp256k1_pubkey *const *)pubkeys, count);
10831090
free_pubkeys(pubkeys, count);
10841091
CHECKRESULT(!result, "secp256k1_musig_pubkey_agg failed");
1085-
1086-
jpubkey = (*penv)->NewByteArray(penv, 32);
1087-
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
10881092
result = secp256k1_xonly_pubkey_serialize(ctx, (unsigned char *)pub, &combined);
1089-
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
10901093
CHECKRESULT(!result, "secp256k1_xonly_pubkey_serialize failed");
10911094

1095+
jpubkey = (*penv)->NewByteArray(penv, 32);
1096+
(*penv)->SetByteArrayRegion(penv, jpubkey, 0, 32, pub);
1097+
10921098
if (jkeyaggcache != NULL)
10931099
{
1094-
pub = (*penv)->GetByteArrayElements(penv, jkeyaggcache, 0);
1095-
memcpy(pub, keyaggcache.data, sizeof(secp256k1_musig_keyagg_cache));
1096-
(*penv)->ReleaseByteArrayElements(penv, jkeyaggcache, pub, 0);
1100+
(*penv)->SetByteArrayRegion(penv, jkeyaggcache, 0, sizeof(secp256k1_musig_keyagg_cache), keyaggcache.data);
10971101
}
10981102
return jpubkey;
10991103
}

tests/build.gradle.kts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
22
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest
33
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeHostTest
44
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest
5+
import java.io.FileOutputStream
56

67
plugins {
78
kotlin("multiplatform")
@@ -93,6 +94,8 @@ if (includeAndroid) {
9394
}
9495
}
9596

97+
val crashLogDir = layout.buildDirectory.dir("crash_logs")
98+
9699
afterEvaluate {
97100
tasks.withType<AbstractTestTask> {
98101
testLogging {
@@ -113,4 +116,36 @@ afterEvaluate {
113116
tasks.withType<KotlinNativeSimulatorTest> {
114117
environment("SIMCTL_CHILD_TEST_RESOURCES_PATH", projectDir.resolve("src/commonTest/resources"))
115118
}
119+
120+
tasks.withType<JavaExec>().configureEach {
121+
doFirst {
122+
val dir = crashLogDir.get().asFile
123+
if (!dir.exists()) dir.mkdirs()
124+
}
125+
126+
jvmArgs = listOf(
127+
"-XX:+ShowMessageBoxOnError",
128+
"-XX:+CrashOnOutOfMemoryError",
129+
"-XX:+CreateCoredumpOnCrash",
130+
"-XX:ErrorFile=${crashLogDir.get().asFile}/hs_err_pid%p.log"
131+
)
132+
133+
// Redirect standard and error output to files
134+
standardOutput = FileOutputStream("${buildDir}/jni_stdout.log")
135+
errorOutput = FileOutputStream("${buildDir}/jni_stderr.log")
136+
}
137+
138+
tasks.withType<Test>().configureEach {
139+
doFirst {
140+
val dir = crashLogDir.get().asFile
141+
if (!dir.exists()) dir.mkdirs()
142+
}
143+
144+
jvmArgs = listOf(
145+
"-XX:+ShowMessageBoxOnError",
146+
"-XX:+CrashOnOutOfMemoryError",
147+
"-XX:+CreateCoredumpOnCrash",
148+
"-XX:ErrorFile=${crashLogDir.get().asFile}/hs_err_pid%p.log"
149+
)
150+
}
116151
}

0 commit comments

Comments
 (0)