diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 495437b..9959fcb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: shell: bash run: | echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV - echo "ANDROID_NDK_VERSION=28.1.13356709" >> $GITHUB_ENV + echo "ANDROID_NDK_VERSION=28.2.13676358" >> $GITHUB_ENV - name: Cached Android NDK if: matrix.os == 'ubuntu-latest' uses: actions/cache@v4 diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 5e0c0ab..d9a41ce 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -51,7 +51,7 @@ jobs: shell: bash run: | echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV - echo "ANDROID_NDK_VERSION=28.1.13356709" >> $GITHUB_ENV + echo "ANDROID_NDK_VERSION=28.2.13676358" >> $GITHUB_ENV - name: Cached Android NDK if: matrix.os == 'ubuntu-latest' uses: actions/cache@v4 @@ -115,6 +115,7 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: 27 + disk-size: 5GB emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none ndk: ${{ env.ANDROID_NDK_VERSION }} cmake: 3.31.5 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ce2a1b..1bc119a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,7 +54,7 @@ jobs: shell: bash run: | echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV - echo "ANDROID_NDK_VERSION=28.1.13356709" >> $GITHUB_ENV + echo "ANDROID_NDK_VERSION=28.2.13676358" >> $GITHUB_ENV - name: Cached Android NDK if: matrix.os == 'ubuntu-latest' uses: actions/cache@v4 @@ -118,6 +118,7 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: 27 + disk-size: 5GB emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none ndk: ${{ env.ANDROID_NDK_VERSION }} cmake: 3.31.5 diff --git a/build.gradle.kts b/build.gradle.kts index 4713d0e..d18d2e3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,12 +1,13 @@ import org.gradle.internal.os.OperatingSystem +import org.gradle.kotlin.dsl.register import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.dokka.Platform import org.jetbrains.kotlin.gradle.dsl.JvmTarget import java.util.* plugins { - kotlin("multiplatform") version "2.2.0" - id("org.jetbrains.dokka") version "1.9.20" + kotlin("multiplatform") version "2.2.21" + id("org.jetbrains.dokka") version "2.1.0" `maven-publish` } @@ -17,13 +18,13 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:8.7.3") + classpath("com.android.tools.build:gradle:8.13.1") } } allprojects { group = "fr.acinq.secp256k1" - version = "0.21.0" + version = "0.22.0-SNAPSHOT" repositories { google() @@ -130,7 +131,7 @@ allprojects { } allprojects { - val javadocJar = tasks.create("javadocJar") { + val javadocJar = tasks.register("javadocJar") { archiveClassifier.set("javadoc") duplicatesStrategy = DuplicatesStrategy.EXCLUDE } @@ -172,25 +173,21 @@ allprojects { if (project.name !in listOf("native", "tests")) { afterEvaluate { - val dokkaOutputDir = layout.buildDirectory.dir("dokka").get().asFile - - tasks.dokkaHtml { - outputDirectory.set(file(dokkaOutputDir)) - dokkaSourceSets { - configureEach { - val platformName = when (platform.get()) { - Platform.jvm -> "jvm" - Platform.js -> "js" - Platform.native -> "native" - Platform.common -> "common" - Platform.wasm -> "wasm" - else -> error("invalid platform ${platform.get()}") - } - displayName.set(platformName) - - perPackageOption { - matchingRegex.set(".*\\.internal.*") // will match all .internal packages and sub-packages - suppress.set(true) + val dokkaOutputDir = layout.buildDirectory.dir("dokka") + + dokka { + moduleName = "secp256k1-kmp" + dokkaPublications.html { + outputDirectory.set(dokkaOutputDir) + dokkaSourceSets { + configureEach { + val platformName = analysisPlatform.get().name + displayName.set(platformName) + + perPackageOption { + matchingRegex.set(".*\\.internal.*") // will match all .internal packages and sub-packages + suppress.set(true) + } } } } @@ -200,8 +197,10 @@ allprojects { delete(dokkaOutputDir) } - javadocJar.dependsOn(deleteDokkaOutputDir, tasks.dokkaHtml) - javadocJar.from(dokkaOutputDir) + javadocJar { + dependsOn(deleteDokkaOutputDir, tasks.dokkaGenerate) + from(dokkaOutputDir) + } } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e644113..1b33c55 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 98fa171..78cb6e1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,8 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip -distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab +distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1aa94a4..23d15a9 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -112,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -203,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -211,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 7101f8e..5eed7ee 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -68,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/jni/android/build.gradle.kts b/jni/android/build.gradle.kts index 495357e..09e414e 100644 --- a/jni/android/build.gradle.kts +++ b/jni/android/build.gradle.kts @@ -1,3 +1,4 @@ +import org.gradle.kotlin.dsl.register import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -40,7 +41,7 @@ android { } } - ndkVersion = "28.1.13356709" + ndkVersion = "28.2.13676358" afterEvaluate { tasks.withType().all { @@ -65,7 +66,7 @@ afterEvaluate { create("android") { artifactId = "secp256k1-kmp-jni-android" from(components["release"]) - val sourcesJar = task("sourcesJar") { + val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") from(android.sourceSets["main"].java.srcDirs) } diff --git a/jni/build.gradle.kts b/jni/build.gradle.kts index 6c15687..ca595cb 100644 --- a/jni/build.gradle.kts +++ b/jni/build.gradle.kts @@ -1,3 +1,4 @@ +import org.gradle.kotlin.dsl.register import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -24,7 +25,7 @@ dependencies { api(rootProject) } -val generateHeaders by tasks.creating(JavaCompile::class) { +val generateHeaders by tasks.registering(JavaCompile::class) { -> group = "build" classpath = sourceSets["main"].compileClasspath destinationDirectory.set(layout.buildDirectory.dir("generated/jni")) @@ -33,7 +34,6 @@ val generateHeaders by tasks.creating(JavaCompile::class) { "-h", layout.buildDirectory.dir("generated./jni").get().asFile.absolutePath, "-d", layout.buildDirectory.dir("generated./jni-tmp").get().asFile.absolutePath ) - // options.verbose = true doLast { layout.buildDirectory.dir("generated/jni-tmp").get().asFile.delete() } @@ -44,7 +44,7 @@ publishing { create("jvm") { artifactId = "secp256k1-kmp-jni-common" from(components["java"]) - val sourcesJar = task("sourcesJar") { + val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") from(sourceSets["main"].allSource) } diff --git a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c index 36f0910..c87c0e2 100644 --- a/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c +++ b/jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c @@ -1,57 +1,54 @@ -#include #include +#include #ifdef WIN32 #define SECP256K1_STATIC // needed on windows when linking to a static version of secp256k1 #endif +#include "fr_acinq_secp256k1_Secp256k1CFunctions.h" #include "include/secp256k1.h" #include "include/secp256k1_ecdh.h" +#include "include/secp256k1_musig.h" #include "include/secp256k1_recovery.h" #include "include/secp256k1_schnorrsig.h" -#include "include/secp256k1_musig.h" -#include "fr_acinq_secp256k1_Secp256k1CFunctions.h" #define SIG_FORMAT_UNKNOWN 0 #define SIG_FORMAT_COMPACT 1 #define SIG_FORMAT_DER 2 -static void JNI_ThrowByName(JNIEnv *penv, const char *name, const char *msg) +static void JNI_ThrowByName(JNIEnv* penv, const char* name, const char* msg) { - jclass cls = (*penv)->FindClass(penv, name); - if (cls != NULL) - { - (*penv)->ThrowNew(penv, cls, msg); - (*penv)->DeleteLocalRef(penv, cls); - } + jclass cls = (*penv)->FindClass(penv, name); + if (cls != NULL) { + (*penv)->ThrowNew(penv, cls, msg); + (*penv)->DeleteLocalRef(penv, cls); + } } -#define CHECKRESULT(errorcheck, message) \ - { \ - if (errorcheck) \ - { \ - JNI_ThrowByName(penv, "fr/acinq/secp256k1/Secp256k1Exception", message); \ - return 0; \ - } \ - } - -#define CHECKRESULT1(errorcheck, message, dosomething) \ - { \ - if (errorcheck) \ - { \ - dosomething; \ - JNI_ThrowByName(penv, "fr/acinq/secp256k1/Secp256k1Exception", message); \ - return 0; \ - } \ - } +#define CHECKRESULT(errorcheck, message) \ + { \ + if (errorcheck) { \ + JNI_ThrowByName(penv, "fr/acinq/secp256k1/Secp256k1Exception", message); \ + return 0; \ + } \ + } + +#define CHECKRESULT1(errorcheck, message, dosomething) \ + { \ + if (errorcheck) { \ + dosomething; \ + JNI_ThrowByName(penv, "fr/acinq/secp256k1/Secp256k1Exception", message); \ + return 0; \ + } \ + } /* * Class: fr_acinq_bitcoin_Secp256k1Bindings * Method: secp256k1_context_create * Signature: (I)J */ -JNIEXPORT jlong JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1create(JNIEnv *penv, jclass clazz, jint flags) +JNIEXPORT jlong JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1create(JNIEnv* penv, jclass clazz, jint flags) { - return (jlong)secp256k1_context_create(flags); + return (jlong)secp256k1_context_create(flags); } /* @@ -59,12 +56,11 @@ JNIEXPORT jlong JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1c * Method: secp256k1_context_destroy * Signature: (J)V */ -JNIEXPORT void JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1destroy(JNIEnv *penv, jclass clazz, jlong ctx) +JNIEXPORT void JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1destroy(JNIEnv* penv, jclass clazz, jlong ctx) { - if (ctx != 0) - { - secp256k1_context_destroy((secp256k1_context *)ctx); - } + if (ctx != 0) { + secp256k1_context_destroy((secp256k1_context*)ctx); + } } /* @@ -72,19 +68,19 @@ JNIEXPORT void JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1co * Method: secp256k1_ec_seckey_verify * Signature: (J[B)I */ -JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1verify(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey) +JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1verify(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jseckey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckey[32]; - int result = 0; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckey[32]; + int result = 0; - if (jctx == 0) return 0; - if (jseckey == NULL) return 0; - if ((*penv)->GetArrayLength(penv, jseckey) != 32) return 0; + if (jctx == 0) return 0; + if (jseckey == NULL) return 0; + if ((*penv)->GetArrayLength(penv, jseckey) != 32) return 0; - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - result = secp256k1_ec_seckey_verify(ctx, (unsigned char *)seckey); - return result; + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + result = secp256k1_ec_seckey_verify(ctx, (unsigned char*)seckey); + return result; } /* @@ -92,30 +88,30 @@ JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec * Method: secp256k1_ec_pubkey_parse * Signature: (J[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1parse(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1parse(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jpubkey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pubkeyBytes[65]; - secp256k1_pubkey pubkey; - size_t size; - int result = 0; - - if (jctx == 0) return 0; - if (jpubkey == NULL) return 0; - - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); - - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pubkeyBytes); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char *)pubkeyBytes, size); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)pubkeyBytes, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pubkeyBytes); - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pubkeyBytes[65]; + secp256k1_pubkey pubkey; + size_t size; + int result = 0; + + if (jctx == 0) return 0; + if (jpubkey == NULL) return 0; + + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); + + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pubkeyBytes); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pubkeyBytes, size); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pubkeyBytes, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pubkeyBytes); + return jpubkey; } /* @@ -123,30 +119,30 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ec_pubkey_create * Signature: (J[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1create(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1create(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jseckey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckey[32], pubkey[65]; - secp256k1_pubkey pub; - int result = 0; - size_t len; - jbyteArray jpubkey = 0; - - if (jseckey == NULL) return NULL; - if (jctx == 0) return NULL; - - CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - result = secp256k1_ec_pubkey_create(ctx, &pub, (unsigned char *)seckey); - CHECKRESULT(!result, "secp256k1_ec_pubkey_create failed"); - - len = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)pubkey, &len, &pub, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pubkey); - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckey[32], pubkey[65]; + secp256k1_pubkey pub; + int result = 0; + size_t len; + jbyteArray jpubkey = 0; + + if (jseckey == NULL) return NULL; + if (jctx == 0) return NULL; + + CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + result = secp256k1_ec_pubkey_create(ctx, &pub, (unsigned char*)seckey); + CHECKRESULT(!result, "secp256k1_ec_pubkey_create failed"); + + len = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pubkey, &len, &pub, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pubkey); + return jpubkey; } /* @@ -154,43 +150,43 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ecdsa_sign * Signature: (J[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1sign(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jmsg, jbyteArray jseckey) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1sign(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jmsg, jbyteArray jseckey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckey[32], msg[32], sig[64]; - secp256k1_ecdsa_signature signature; - int result = 0; - jbyteArray jsig; - - if (jctx == 0) return NULL; - if (jmsg == NULL) return NULL; - if (jseckey == NULL) return NULL; - - CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); - CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message key must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); - - result = secp256k1_ecdsa_sign(ctx, &signature, (unsigned char *)msg, (unsigned char *)seckey, NULL, NULL); - CHECKRESULT(!result, "secp256k1_ecdsa_sign failed"); - - result = secp256k1_ecdsa_signature_serialize_compact(ctx, (unsigned char *)sig, &signature); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed"); - - jsig = (*penv)->NewByteArray(penv, 64); - (*penv)->SetByteArrayRegion(penv, jsig, 0, 64, sig); - return jsig; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckey[32], msg[32], sig[64]; + secp256k1_ecdsa_signature signature; + int result = 0; + jbyteArray jsig; + + if (jctx == 0) return NULL; + if (jmsg == NULL) return NULL; + if (jseckey == NULL) return NULL; + + CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); + CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message key must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); + + result = secp256k1_ecdsa_sign(ctx, &signature, (unsigned char*)msg, (unsigned char*)seckey, NULL, NULL); + CHECKRESULT(!result, "secp256k1_ecdsa_sign failed"); + + result = secp256k1_ecdsa_signature_serialize_compact(ctx, (unsigned char*)sig, &signature); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed"); + + jsig = (*penv)->NewByteArray(penv, 64); + (*penv)->SetByteArrayRegion(penv, jsig, 0, 64, sig); + return jsig; } static int GetSignatureFormat(size_t size) { - if (size == 64) - return SIG_FORMAT_COMPACT; - if (size < 64) - return SIG_FORMAT_UNKNOWN; - if (size > 73) - return SIG_FORMAT_UNKNOWN; - return SIG_FORMAT_DER; + if (size == 64) + return SIG_FORMAT_COMPACT; + if (size < 64) + return SIG_FORMAT_UNKNOWN; + if (size > 73) + return SIG_FORMAT_UNKNOWN; + return SIG_FORMAT_DER; } /* @@ -198,49 +194,48 @@ static int GetSignatureFormat(size_t size) * Method: secp256k1_ecdsa_verify * Signature: (J[B[B[B)I */ -JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1verify(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jbyteArray jpubkey) +JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1verify(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jbyteArray jpubkey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pub[65], msg[32], sig[73]; - secp256k1_ecdsa_signature signature; - secp256k1_pubkey pubkey; - size_t sigSize, pubSize; - int result = 0; - - if (jctx == 0) return 0; - if (jsig == NULL) return 0; - if (jmsg == NULL) return 0; - if (jpubkey == NULL) return 0; - - sigSize = (*penv)->GetArrayLength(penv, jsig); - int sigFormat = GetSignatureFormat(sigSize); - CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size"); - - pubSize = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((pubSize != 33) && (pubSize != 65), "invalid public key size"); - - CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); - - (*penv)->GetByteArrayRegion(penv, jsig, 0, sigSize, sig); - switch (sigFormat) - { - case SIG_FORMAT_COMPACT: - result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature, (unsigned char *)sig); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed"); - break; - case SIG_FORMAT_DER: - result = secp256k1_ecdsa_signature_parse_der(ctx, &signature, (unsigned char *)sig, sigSize); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed"); - break; - } - - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, pubSize, pub); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char *)pub, pubSize); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - - (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); - result = secp256k1_ecdsa_verify(ctx, &signature, (unsigned char *)msg, &pubkey); - return result; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pub[65], msg[32], sig[73]; + secp256k1_ecdsa_signature signature; + secp256k1_pubkey pubkey; + size_t sigSize, pubSize; + int result = 0; + + if (jctx == 0) return 0; + if (jsig == NULL) return 0; + if (jmsg == NULL) return 0; + if (jpubkey == NULL) return 0; + + sigSize = (*penv)->GetArrayLength(penv, jsig); + int sigFormat = GetSignatureFormat(sigSize); + CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size"); + + pubSize = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((pubSize != 33) && (pubSize != 65), "invalid public key size"); + + CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); + + (*penv)->GetByteArrayRegion(penv, jsig, 0, sigSize, sig); + switch (sigFormat) { + case SIG_FORMAT_COMPACT: + result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature, (unsigned char*)sig); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed"); + break; + case SIG_FORMAT_DER: + result = secp256k1_ecdsa_signature_parse_der(ctx, &signature, (unsigned char*)sig, sigSize); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed"); + break; + } + + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, pubSize, pub); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, pubSize); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); + result = secp256k1_ecdsa_verify(ctx, &signature, (unsigned char*)msg, &pubkey); + return result; } /* @@ -248,44 +243,43 @@ JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec * Method: secp256k1_ecdsa_signature_normalize * Signature: (J[B[B)I */ -JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1signature_1normalize(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsigin, jbyteArray jsigout) +JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1signature_1normalize(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsigin, jbyteArray jsigout) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte sig[73]; - secp256k1_ecdsa_signature signature_in, signature_out; - size_t size; - int result = 0; - int return_value = 0; - int sigFormat = SIG_FORMAT_UNKNOWN; - - if (jctx == 0) return 0; - if (jsigin == NULL) return 0; - if (jsigout == NULL) return 0; - - size = (*penv)->GetArrayLength(penv, jsigin); - sigFormat = GetSignatureFormat(size); - CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size"); - CHECKRESULT((*penv)->GetArrayLength(penv, jsigout) != 64, "output signature length must be 64 bytes"); - - (*penv)->GetByteArrayRegion(penv, jsigin, 0, size, sig); - switch (sigFormat) - { - case SIG_FORMAT_COMPACT: - result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature_in, (unsigned char *)sig); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed"); - break; - case SIG_FORMAT_DER: - result = secp256k1_ecdsa_signature_parse_der(ctx, &signature_in, (unsigned char *)sig, size); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed"); - break; - } - return_value = secp256k1_ecdsa_signature_normalize(ctx, &signature_out, &signature_in); - result = secp256k1_ecdsa_signature_serialize_compact(ctx, (unsigned char *)sig, &signature_out); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed"); - - (*penv)->SetByteArrayRegion(penv, jsigout, 0, 64, sig); - - return return_value; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte sig[73]; + secp256k1_ecdsa_signature signature_in, signature_out; + size_t size; + int result = 0; + int return_value = 0; + int sigFormat = SIG_FORMAT_UNKNOWN; + + if (jctx == 0) return 0; + if (jsigin == NULL) return 0; + if (jsigout == NULL) return 0; + + size = (*penv)->GetArrayLength(penv, jsigin); + sigFormat = GetSignatureFormat(size); + CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size"); + CHECKRESULT((*penv)->GetArrayLength(penv, jsigout) != 64, "output signature length must be 64 bytes"); + + (*penv)->GetByteArrayRegion(penv, jsigin, 0, size, sig); + switch (sigFormat) { + case SIG_FORMAT_COMPACT: + result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature_in, (unsigned char*)sig); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed"); + break; + case SIG_FORMAT_DER: + result = secp256k1_ecdsa_signature_parse_der(ctx, &signature_in, (unsigned char*)sig, size); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed"); + break; + } + return_value = secp256k1_ecdsa_signature_normalize(ctx, &signature_out, &signature_in); + result = secp256k1_ecdsa_signature_serialize_compact(ctx, (unsigned char*)sig, &signature_out); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed"); + + (*penv)->SetByteArrayRegion(penv, jsigout, 0, 64, sig); + + return return_value; } /* @@ -293,22 +287,22 @@ JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec * Method: secp256k1_ec_seckey_negate * Signature: (J[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1negate(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1negate(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jseckey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckey[32]; - int result = 0; - - if (jctx == 0) return 0; - if (jseckey == NULL) return 0; - CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - result = secp256k1_ec_seckey_negate(ctx, (unsigned char *)seckey); - CHECKRESULT(!result, "secp256k1_ec_seckey_negate failed"); - - jseckey = (*penv)->NewByteArray(penv, 32); - (*penv)->SetByteArrayRegion(penv, jseckey, 0, 32, seckey); - return jseckey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckey[32]; + int result = 0; + + if (jctx == 0) return 0; + if (jseckey == NULL) return 0; + CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + result = secp256k1_ec_seckey_negate(ctx, (unsigned char*)seckey); + CHECKRESULT(!result, "secp256k1_ec_seckey_negate failed"); + + jseckey = (*penv)->NewByteArray(penv, 32); + (*penv)->SetByteArrayRegion(penv, jseckey, 0, 32, seckey); + return jseckey; } /* @@ -316,33 +310,33 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ec_pubkey_negate * Signature: (J[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1negate(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1negate(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jpubkey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pub[65]; - secp256k1_pubkey pubkey; - size_t size; - int result = 0; - - if (jctx == 0) return 0; - if (jpubkey == NULL) return 0; - - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char *)pub, size); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - - result = secp256k1_ec_pubkey_negate(ctx, &pubkey); - CHECKRESULT(!result, "secp256k1_ec_pubkey_negate failed"); - - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pub[65]; + secp256k1_pubkey pubkey; + size_t size; + int result = 0; + + if (jctx == 0) return 0; + if (jpubkey == NULL) return 0; + + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, size); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + result = secp256k1_ec_pubkey_negate(ctx, &pubkey); + CHECKRESULT(!result, "secp256k1_ec_pubkey_negate failed"); + + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); + return jpubkey; } /* @@ -350,27 +344,27 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ec_seckey_tweak_add * Signature: (J[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1tweak_1add(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jtweak) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1tweak_1add(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jtweak) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckey[32], tweak[32]; - int result = 0; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckey[32], tweak[32]; + int result = 0; - if (jctx == 0) return NULL; - if (jseckey == NULL) return NULL; - if (jtweak == NULL) return NULL; + if (jctx == 0) return NULL; + if (jseckey == NULL) return NULL; + if (jtweak == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); - CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); + CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); + CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); - result = secp256k1_ec_seckey_tweak_add(ctx, (unsigned char *)seckey, (unsigned char *)tweak); - CHECKRESULT(!result, "secp256k1_ec_seckey_tweak_add failed"); + result = secp256k1_ec_seckey_tweak_add(ctx, (unsigned char*)seckey, (unsigned char*)tweak); + CHECKRESULT(!result, "secp256k1_ec_seckey_tweak_add failed"); - jseckey = (*penv)->NewByteArray(penv, 32); - (*penv)->SetByteArrayRegion(penv, jseckey, 0, 32, seckey); - return jseckey; + jseckey = (*penv)->NewByteArray(penv, 32); + (*penv)->SetByteArrayRegion(penv, jseckey, 0, 32, seckey); + return jseckey; } /* @@ -378,37 +372,37 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ec_pubkey_tweak_add * Signature: (J[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1add(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey, jbyteArray jtweak) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1add(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jpubkey, jbyteArray jtweak) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pub[65], tweak[32]; - secp256k1_pubkey pubkey; - size_t size; - int result = 0; - - if (jctx == 0) return NULL; - if (jpubkey == NULL) return NULL; - if (jtweak == NULL) return NULL; - - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); - CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); - - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char *)pub, size); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - - (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); - result = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, (unsigned char *)tweak); - CHECKRESULT(!result, "secp256k1_ec_pubkey_tweak_add failed"); - - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pub[65], tweak[32]; + secp256k1_pubkey pubkey; + size_t size; + int result = 0; + + if (jctx == 0) return NULL; + if (jpubkey == NULL) return NULL; + if (jtweak == NULL) return NULL; + + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); + CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); + + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, size); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); + result = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, (unsigned char*)tweak); + CHECKRESULT(!result, "secp256k1_ec_pubkey_tweak_add failed"); + + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); + return jpubkey; } /* @@ -416,26 +410,26 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ec_seckey_tweak_mul * Signature: (J[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1tweak_1mul(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jtweak) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1tweak_1mul(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jtweak) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckey[32], tweak[32]; - int result = 0; - - if (jctx == 0) return NULL; - if (jseckey == NULL) return NULL; - if (jtweak == NULL) return NULL; - - CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); - CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); - result = secp256k1_ec_seckey_tweak_mul(ctx, (unsigned char *)seckey, (unsigned char *)tweak); - CHECKRESULT(!result, "secp256k1_ec_seckey_tweak_mul failed"); - - jseckey = (*penv)->NewByteArray(penv, 32); - (*penv)->SetByteArrayRegion(penv, jseckey, 0, 32, seckey); - return jseckey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckey[32], tweak[32]; + int result = 0; + + if (jctx == 0) return NULL; + if (jseckey == NULL) return NULL; + if (jtweak == NULL) return NULL; + + CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); + CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); + result = secp256k1_ec_seckey_tweak_mul(ctx, (unsigned char*)seckey, (unsigned char*)tweak); + CHECKRESULT(!result, "secp256k1_ec_seckey_tweak_mul failed"); + + jseckey = (*penv)->NewByteArray(penv, 32); + (*penv)->SetByteArrayRegion(penv, jseckey, 0, 32, seckey); + return jseckey; } /* @@ -443,48 +437,47 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ec_pubkey_tweak_mul * Signature: (J[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1mul(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey, jbyteArray jtweak) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1mul(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jpubkey, jbyteArray jtweak) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pub[65], tweak[32]; - secp256k1_pubkey pubkey; - size_t size; - int result = 0; - - if (jctx == 0) return NULL; - if (jpubkey == NULL) return NULL; - if (jtweak == NULL) return NULL; - - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); - CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char *)pub, size); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - - (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); - result = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, (unsigned char *)tweak); - CHECKRESULT(!result, "secp256k1_ec_pubkey_tweak_mul failed"); - - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pub[65], tweak[32]; + secp256k1_pubkey pubkey; + size_t size; + int result = 0; + + if (jctx == 0) return NULL; + if (jpubkey == NULL) return NULL; + if (jtweak == NULL) return NULL; + + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); + CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, size); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + (*penv)->GetByteArrayRegion(penv, jtweak, 0, 32, tweak); + result = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, (unsigned char*)tweak); + CHECKRESULT(!result, "secp256k1_ec_pubkey_tweak_mul failed"); + + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); + return jpubkey; } -static void free_pubkeys(secp256k1_pubkey **pubkeys, size_t count) +static void free_pubkeys(secp256k1_pubkey** pubkeys, size_t count) { - size_t i; - if (pubkeys == NULL) return; - for (i = 0; i < count; i++) - { - if (pubkeys[i] != NULL) - free(pubkeys[i]); - } - free(pubkeys); + size_t i; + if (pubkeys == NULL) return; + for (i = 0; i < count; i++) { + if (pubkeys[i] != NULL) + free(pubkeys[i]); + } + free(pubkeys); } /* @@ -492,49 +485,46 @@ static void free_pubkeys(secp256k1_pubkey **pubkeys, size_t count) * Method: secp256k1_ec_pubkey_combine * Signature: (J[[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1combine(JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jpubkeys) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1combine(JNIEnv* penv, jclass clazz, jlong jctx, jobjectArray jpubkeys) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pub[65]; - secp256k1_pubkey **pubkeys; - secp256k1_pubkey combined; - jbyteArray jpubkey; - size_t size, count; - size_t i; - int result = 0; - - if (jctx == 0) - return NULL; - if (jpubkeys == NULL) - return NULL; - - count = (*penv)->GetArrayLength(penv, jpubkeys); - CHECKRESULT(count < 1, "pubkey array cannot be empty") - pubkeys = calloc(count, sizeof(secp256k1_pubkey *)); - CHECKRESULT(pubkeys == NULL, "memory allocation failed"); - - for (i = 0; i < count; i++) - { - pubkeys[i] = calloc(1, sizeof(secp256k1_pubkey)); - CHECKRESULT1(pubkeys[i] == NULL, "memory allocation failed", free_pubkeys(pubkeys, i)); - jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i); - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, i)); - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); - result = secp256k1_ec_pubkey_parse(ctx, pubkeys[i], (unsigned char *)pub, size); - CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(pubkeys, i)); - } - result = secp256k1_ec_pubkey_combine(ctx, &combined, (const secp256k1_pubkey *const *)pubkeys, count); - free_pubkeys(pubkeys, count); - CHECKRESULT(!result, "secp256k1_ec_pubkey_combine failed"); - - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)pub, &size, &combined, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pub[65]; + secp256k1_pubkey** pubkeys; + secp256k1_pubkey combined; + jbyteArray jpubkey; + size_t size, count; + size_t i; + int result = 0; + + if (jctx == 0) return NULL; + if (jpubkeys == NULL) return NULL; + + count = (*penv)->GetArrayLength(penv, jpubkeys); + CHECKRESULT(count < 1, "pubkey array cannot be empty") + pubkeys = calloc(count, sizeof(secp256k1_pubkey*)); + CHECKRESULT(pubkeys == NULL, "memory allocation failed"); + + for (i = 0; i < count; i++) { + pubkeys[i] = calloc(1, sizeof(secp256k1_pubkey)); + CHECKRESULT1(pubkeys[i] == NULL, "memory allocation failed", free_pubkeys(pubkeys, count)); + jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i); + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, count)); + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); + result = secp256k1_ec_pubkey_parse(ctx, pubkeys[i], (unsigned char*)pub, size); + CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(pubkeys, count)); + } + result = secp256k1_ec_pubkey_combine(ctx, &combined, (const secp256k1_pubkey* const*)pubkeys, count); + free_pubkeys(pubkeys, count); + CHECKRESULT(!result, "secp256k1_ec_pubkey_combine failed"); + + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &combined, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); + return jpubkey; } /* @@ -542,34 +532,34 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ecdh * Signature: (J[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdh(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jpubkey) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdh(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jpubkey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckeyBytes[32], pubkeyBytes[65], output[32]; - secp256k1_pubkey pubkey; - jbyteArray joutput; - size_t size; - int result; - - if (jctx == 0) return NULL; - if (jseckey == NULL) return NULL; - if (jpubkey == NULL) return NULL; - - CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "invalid private key size"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckeyBytes); - - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pubkeyBytes); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char *)pubkeyBytes, size); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - - result = secp256k1_ecdh(ctx, (unsigned char *)output, &pubkey, (unsigned char *)seckeyBytes, NULL, NULL); - CHECKRESULT(!result, "secp256k1_ecdh failed"); - - joutput = (*penv)->NewByteArray(penv, 32); - (*penv)->SetByteArrayRegion(penv, joutput, 0, 32, output); - return joutput; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckeyBytes[32], pubkeyBytes[65], output[32]; + secp256k1_pubkey pubkey; + jbyteArray joutput; + size_t size; + int result; + + if (jctx == 0) return NULL; + if (jseckey == NULL) return NULL; + if (jpubkey == NULL) return NULL; + + CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "invalid private key size"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckeyBytes); + + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pubkeyBytes); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pubkeyBytes, size); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + result = secp256k1_ecdh(ctx, (unsigned char*)output, &pubkey, (unsigned char*)seckeyBytes, NULL, NULL); + CHECKRESULT(!result, "secp256k1_ecdh failed"); + + joutput = (*penv)->NewByteArray(penv, 32); + (*penv)->SetByteArrayRegion(penv, joutput, 0, 32, output); + return joutput; } /* @@ -577,55 +567,54 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_ecdsa_recover * Signature: (J[B[BI)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1recover(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jint recid) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1recover(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jint recid) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte sig[73], msg[32], pub[65]; - jbyteArray jpubkey; - secp256k1_pubkey pubkey; - secp256k1_ecdsa_recoverable_signature signature; - secp256k1_ecdsa_signature dummy; - unsigned char dummyBytes[64]; - size_t sigSize, size; - int result; - - if (jctx == 0) return NULL; - if (jsig == NULL) return NULL; - if (jmsg == NULL) return NULL; - CHECKRESULT(recid < 0 || recid > 3, "invalid recovery id"); - - sigSize = (*penv)->GetArrayLength(penv, jsig); - int sigFormat = GetSignatureFormat(sigSize); - CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size"); - - CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jsig, 0, sigSize, sig); - switch (sigFormat) - { - case SIG_FORMAT_COMPACT: - result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, (unsigned char *)sig, recid); - CHECKRESULT(!result, "secp256k1_ecdsa_recoverable_signature_parse_compact failed"); - break; - case SIG_FORMAT_DER: - result = secp256k1_ecdsa_signature_parse_der(ctx, &dummy, (unsigned char *)sig, sigSize); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed"); - result = secp256k1_ecdsa_signature_serialize_compact(ctx, dummyBytes, &dummy); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed"); - result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, dummyBytes, recid); - CHECKRESULT(!result, "secp256k1_ecdsa_recoverable_signature_parse_compact failed"); - break; - } - (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); - result = secp256k1_ecdsa_recover(ctx, &pubkey, &signature, (unsigned char *)msg); - CHECKRESULT(!result, "secp256k1_ecdsa_recover failed"); - - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char *)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte sig[73], msg[32], pub[65]; + jbyteArray jpubkey; + secp256k1_pubkey pubkey; + secp256k1_ecdsa_recoverable_signature signature; + secp256k1_ecdsa_signature dummy; + unsigned char dummyBytes[64]; + size_t sigSize, size; + int result; + + if (jctx == 0) return NULL; + if (jsig == NULL) return NULL; + if (jmsg == NULL) return NULL; + CHECKRESULT(recid < 0 || recid > 3, "invalid recovery id"); + + sigSize = (*penv)->GetArrayLength(penv, jsig); + int sigFormat = GetSignatureFormat(sigSize); + CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size"); + + CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jsig, 0, sigSize, sig); + switch (sigFormat) { + case SIG_FORMAT_COMPACT: + result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, (unsigned char*)sig, recid); + CHECKRESULT(!result, "secp256k1_ecdsa_recoverable_signature_parse_compact failed"); + break; + case SIG_FORMAT_DER: + result = secp256k1_ecdsa_signature_parse_der(ctx, &dummy, (unsigned char*)sig, sigSize); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed"); + result = secp256k1_ecdsa_signature_serialize_compact(ctx, dummyBytes, &dummy); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed"); + result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, dummyBytes, recid); + CHECKRESULT(!result, "secp256k1_ecdsa_recoverable_signature_parse_compact failed"); + break; + } + (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); + result = secp256k1_ecdsa_recover(ctx, &pubkey, &signature, (unsigned char*)msg); + CHECKRESULT(!result, "secp256k1_ecdsa_recover failed"); + + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); + return jpubkey; } /* @@ -633,29 +622,29 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_compact_to_der * Signature: (J[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1compact_1to_1der(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsig) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1compact_1to_1der(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsig) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte sig[64]; - secp256k1_ecdsa_signature signature; - unsigned char der[73]; - size_t size; - int result = 0; - - if (jctx == 0) return 0; - if (jsig == NULL) return 0; - CHECKRESULT((*penv)->GetArrayLength(penv, jsig) != 64, "invalid signature size"); - - (*penv)->GetByteArrayRegion(penv, jsig, 0, 64, sig); - result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature, (unsigned char *)sig); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed"); - - size = 73; - result = secp256k1_ecdsa_signature_serialize_der(ctx, der, &size, &signature); - CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_der failed"); - jsig = (*penv)->NewByteArray(penv, size); - (*penv)->SetByteArrayRegion(penv, jsig, 0, size, der); - return jsig; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte sig[64]; + secp256k1_ecdsa_signature signature; + unsigned char der[73]; + size_t size; + int result = 0; + + if (jctx == 0) return 0; + if (jsig == NULL) return 0; + CHECKRESULT((*penv)->GetArrayLength(penv, jsig) != 64, "invalid signature size"); + + (*penv)->GetByteArrayRegion(penv, jsig, 0, 64, sig); + result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature, (unsigned char*)sig); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed"); + + size = 73; + result = secp256k1_ecdsa_signature_serialize_der(ctx, der, &size, &signature); + CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_der failed"); + jsig = (*penv)->NewByteArray(penv, size); + (*penv)->SetByteArrayRegion(penv, jsig, 0, size, (jbyte*)der); + return jsig; } /* @@ -663,41 +652,39 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_schnorrsig_sign * Signature: (J[B[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1schnorrsig_1sign(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jmsg, jbyteArray jseckey, jbyteArray jauxrand32) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1schnorrsig_1sign(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jmsg, jbyteArray jseckey, jbyteArray jauxrand32) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte seckey[32], msg[32], auxrand32[32]; - secp256k1_keypair keypair; - unsigned char signature[64]; - int result = 0; - jbyteArray jsig; - - if (jctx == 0) return NULL; - if (jmsg == NULL) return NULL; - if (jseckey == NULL)return NULL; - - CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); - CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); - if (jauxrand32 != 0) - { - CHECKRESULT((*penv)->GetArrayLength(penv, jauxrand32) != 32, "auxiliary random data must be 32 bytes"); - } - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - result = secp256k1_keypair_create(ctx, &keypair, (const unsigned char*)seckey); - CHECKRESULT(!result, "secp256k1_keypair_create failed"); - - (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); - if (jauxrand32 != 0) - { - (*penv)->GetByteArrayRegion(penv, jauxrand32, 0, 32, auxrand32); - } - - result = secp256k1_schnorrsig_sign32(ctx, signature, (unsigned char *)msg, &keypair, jauxrand32 != 0 ? auxrand32 : NULL); - CHECKRESULT(!result, "secp256k1_schnorrsig_sign failed"); - - jsig = (*penv)->NewByteArray(penv, 64); - (*penv)->SetByteArrayRegion(penv, jsig, 0, 64, signature); - return jsig; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte seckey[32], msg[32], auxrand32[32]; + secp256k1_keypair keypair; + unsigned char signature[64]; + int result = 0; + jbyteArray jsig; + + if (jctx == 0) return NULL; + if (jmsg == NULL) return NULL; + if (jseckey == NULL) return NULL; + + CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes"); + CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); + if (jauxrand32 != 0) { + CHECKRESULT((*penv)->GetArrayLength(penv, jauxrand32) != 32, "auxiliary random data must be 32 bytes"); + } + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + result = secp256k1_keypair_create(ctx, &keypair, (const unsigned char*)seckey); + CHECKRESULT(!result, "secp256k1_keypair_create failed"); + + (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); + if (jauxrand32 != 0) { + (*penv)->GetByteArrayRegion(penv, jauxrand32, 0, 32, auxrand32); + } + + result = secp256k1_schnorrsig_sign32(ctx, signature, (unsigned char*)msg, &keypair, jauxrand32 != 0 ? (const unsigned char*)auxrand32 : NULL); + CHECKRESULT(!result, "secp256k1_schnorrsig_sign failed"); + + jsig = (*penv)->NewByteArray(penv, 64); + (*penv)->SetByteArrayRegion(penv, jsig, 0, 64, (const jbyte*)signature); + return jsig; } /* @@ -705,30 +692,30 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_schnorrsig_verify * Signature: (J[B[B[B)I */ -JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1schnorrsig_1verify(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jbyteArray jpubkey) +JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1schnorrsig_1verify(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jbyteArray jpubkey) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pub[32], msg[32], sig[64]; - secp256k1_xonly_pubkey pubkey; - int result = 0; - - if (jctx == 0) return 0; - if (jsig == NULL) return 0; - if (jmsg == NULL) return 0; - if (jpubkey == NULL) return 0; - - CHECKRESULT((*penv)->GetArrayLength(penv, jsig) != 64, "signature must be 64 bytes"); - CHECKRESULT((*penv)->GetArrayLength(penv, jpubkey) != 32, "public key must be 32 bytes"); - CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); - - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, 32, pub); - result = secp256k1_xonly_pubkey_parse(ctx, &pubkey, (unsigned char *)pub); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - - (*penv)->GetByteArrayRegion(penv, jsig, 0, 64, sig); - (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); - result = secp256k1_schnorrsig_verify(ctx, (unsigned char *)sig, (unsigned char *)msg, 32, &pubkey); - return result; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pub[32], msg[32], sig[64]; + secp256k1_xonly_pubkey pubkey; + int result = 0; + + if (jctx == 0) return 0; + if (jsig == NULL) return 0; + if (jmsg == NULL) return 0; + if (jpubkey == NULL) return 0; + + CHECKRESULT((*penv)->GetArrayLength(penv, jsig) != 64, "signature must be 64 bytes"); + CHECKRESULT((*penv)->GetArrayLength(penv, jpubkey) != 32, "public key must be 32 bytes"); + CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes"); + + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, 32, pub); + result = secp256k1_xonly_pubkey_parse(ctx, &pubkey, (unsigned char*)pub); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + (*penv)->GetByteArrayRegion(penv, jsig, 0, 64, sig); + (*penv)->GetByteArrayRegion(penv, jmsg, 0, 32, msg); + result = secp256k1_schnorrsig_verify(ctx, (unsigned char*)sig, (unsigned char*)msg, 32, &pubkey); + return result; } // session_id32: ByteArray, seckey: ByteArray?, pubkey: ByteArray, msg32: ByteArray?, keyagg_cache: ByteArray?, extra_input32: ByteArray? @@ -737,148 +724,140 @@ JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1sc * Method: secp256k1_musig_nonce_gen * Signature: (J[B[B[B[B[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1gen(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsession_id32, jbyteArray jseckey, jbyteArray jpubkey, jbyteArray jmsg32, jbyteArray jkeyaggcache, jbyteArray jextra_input32) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1gen(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsession_id32, jbyteArray jseckey, jbyteArray jpubkey, jbyteArray jmsg32, jbyteArray jkeyaggcache, jbyteArray jextra_input32) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - int result = 0; - size_t size; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_secnonce secnonce; - unsigned char session_id32[32]; - jbyte pubkeyBytes[65]; - secp256k1_pubkey pubkey; - unsigned char seckey[32]; - unsigned char msg32[32]; - secp256k1_musig_keyagg_cache keyaggcache; - unsigned char extra_input32[32]; - jbyteArray jnonce; - unsigned char nonce[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE + fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; - - if (jctx == 0) return NULL; - - if (jsession_id32 == 0) return NULL; - size = (*penv)->GetArrayLength(penv, jsession_id32); - CHECKRESULT(size != 32, "invalid session_id size"); - (*penv)->GetByteArrayRegion(penv, jsession_id32, 0, 32, (jbyte*)session_id32); - - if (jseckey != NULL) - { - size = (*penv)->GetArrayLength(penv, jseckey); - CHECKRESULT(size != 32, "invalid private key size"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, (jbyte*)seckey); - } - - if (jpubkey == NULL) return NULL; - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pubkeyBytes); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pubkeyBytes, size); - CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); - - if (jmsg32 != NULL) - { - size = (*penv)->GetArrayLength(penv, jmsg32); - CHECKRESULT(size != 32, "invalid message size"); - (*penv)->GetByteArrayRegion(penv, jmsg32, 0, 32, msg32); - } - - if (jkeyaggcache != NULL) - { - size = (*penv)->GetArrayLength(penv, jkeyaggcache); - CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, size, keyaggcache.data); - } - - if (jextra_input32 != NULL) - { - size = (*penv)->GetArrayLength(penv, jextra_input32); - CHECKRESULT(size != 32, "invalid extra input size"); - (*penv)->GetByteArrayRegion(penv, jextra_input32, 0, size, extra_input32); - } - - result = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_id32, - jseckey == NULL ? NULL : seckey, &pubkey, - jmsg32 == NULL ? NULL : msg32, jkeyaggcache == NULL ? NULL : &keyaggcache, jextra_input32 == NULL ? NULL : extra_input32); - CHECKRESULT(!result, "secp256k1_musig_nonce_gen failed"); - - 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)); - (*penv)->SetByteArrayRegion(penv, jnonce, 0, sizeof(nonce), nonce); - return jnonce; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + int result = 0; + size_t size; + secp256k1_musig_pubnonce pubnonce; + secp256k1_musig_secnonce secnonce; + unsigned char session_id32[32]; + jbyte pubkeyBytes[65]; + secp256k1_pubkey pubkey; + unsigned char seckey[32]; + unsigned char msg32[32]; + secp256k1_musig_keyagg_cache keyaggcache; + unsigned char extra_input32[32]; + jbyteArray jnonce; + unsigned char nonce[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE + fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; + + if (jctx == 0) return NULL; + + if (jsession_id32 == 0) return NULL; + size = (*penv)->GetArrayLength(penv, jsession_id32); + CHECKRESULT(size != 32, "invalid session_id size"); + (*penv)->GetByteArrayRegion(penv, jsession_id32, 0, 32, (jbyte*)session_id32); + + if (jseckey != NULL) { + size = (*penv)->GetArrayLength(penv, jseckey); + CHECKRESULT(size != 32, "invalid private key size"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, (jbyte*)seckey); + } + + if (jpubkey == NULL) return NULL; + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pubkeyBytes); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pubkeyBytes, size); + CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed"); + + if (jmsg32 != NULL) { + size = (*penv)->GetArrayLength(penv, jmsg32); + CHECKRESULT(size != 32, "invalid message size"); + (*penv)->GetByteArrayRegion(penv, jmsg32, 0, 32, (jbyte*)msg32); + } + + if (jkeyaggcache != NULL) { + size = (*penv)->GetArrayLength(penv, jkeyaggcache); + CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, size, (jbyte*)keyaggcache.data); + } + + if (jextra_input32 != NULL) { + size = (*penv)->GetArrayLength(penv, jextra_input32); + CHECKRESULT(size != 32, "invalid extra input size"); + (*penv)->GetByteArrayRegion(penv, jextra_input32, 0, size, (jbyte*)extra_input32); + } + + result = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_id32, + jseckey == NULL ? NULL : seckey, &pubkey, + jmsg32 == NULL ? NULL : msg32, jkeyaggcache == NULL ? NULL : &keyaggcache, jextra_input32 == NULL ? NULL : extra_input32); + CHECKRESULT(!result, "secp256k1_musig_nonce_gen failed"); + + 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)); + (*penv)->SetByteArrayRegion(penv, jnonce, 0, sizeof(nonce), (const jbyte*)nonce); + return jnonce; } -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1gen_1counter(JNIEnv *penv, jclass clazz, jlong jctx, jlong jcounter, jbyteArray jseckey, jbyteArray jmsg32, jbyteArray jkeyaggcache, jbyteArray jextra_input32) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1gen_1counter(JNIEnv* penv, jclass clazz, jlong jctx, jlong jcounter, jbyteArray jseckey, jbyteArray jmsg32, jbyteArray jkeyaggcache, jbyteArray jextra_input32) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - int result = 0; - size_t size; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_secnonce secnonce; - jbyte seckey[32]; - unsigned char msg32[32]; - secp256k1_keypair keypair; - secp256k1_musig_keyagg_cache keyaggcache; - unsigned char extra_input32[32]; - jbyteArray jnonce; - unsigned char nonce[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE + fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; - - if (jctx == 0) return NULL; - - if (jseckey == NULL) return NULL; - size = (*penv)->GetArrayLength(penv, jseckey); - CHECKRESULT(size != 32, "invalid private key size"); - (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); - result = secp256k1_keypair_create(ctx, &keypair, (const unsigned char*)seckey); - CHECKRESULT(!result, "secp256k1_keypair_create failed"); - - if (jmsg32 != NULL) - { - size = (*penv)->GetArrayLength(penv, jmsg32); - CHECKRESULT(size != 32, "invalid message size"); - (*penv)->GetByteArrayRegion(penv, jmsg32, 0, 32, (jbyte*)msg32); - } - - if (jkeyaggcache != NULL) - { - size = (*penv)->GetArrayLength(penv, jkeyaggcache); - CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, size, (jbyte*)keyaggcache.data); - } - - if (jextra_input32 != NULL) - { - size = (*penv)->GetArrayLength(penv, jextra_input32); - CHECKRESULT(size != 32, "invalid extra input size"); - (*penv)->GetByteArrayRegion(penv, jextra_input32, 0, 32, (jbyte*)extra_input32); - } - - result = secp256k1_musig_nonce_gen_counter(ctx, &secnonce, &pubnonce, jcounter, - &keypair, - jmsg32 == NULL ? NULL : msg32, jkeyaggcache == NULL ? NULL : &keyaggcache, jextra_input32 == NULL ? NULL : extra_input32); - CHECKRESULT(!result, "secp256k1_musig_nonce_gen failed"); - - 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)); - (*penv)->SetByteArrayRegion(penv, jnonce, 0, sizeof(nonce), (const jbyte*)nonce); - return jnonce; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + int result = 0; + size_t size; + secp256k1_musig_pubnonce pubnonce; + secp256k1_musig_secnonce secnonce; + jbyte seckey[32]; + unsigned char msg32[32]; + secp256k1_keypair keypair; + secp256k1_musig_keyagg_cache keyaggcache; + unsigned char extra_input32[32]; + jbyteArray jnonce; + unsigned char nonce[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE + fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; + + if (jctx == 0) return NULL; + + if (jseckey == NULL) return NULL; + size = (*penv)->GetArrayLength(penv, jseckey); + CHECKRESULT(size != 32, "invalid private key size"); + (*penv)->GetByteArrayRegion(penv, jseckey, 0, 32, seckey); + result = secp256k1_keypair_create(ctx, &keypair, (const unsigned char*)seckey); + CHECKRESULT(!result, "secp256k1_keypair_create failed"); + + if (jmsg32 != NULL) { + size = (*penv)->GetArrayLength(penv, jmsg32); + CHECKRESULT(size != 32, "invalid message size"); + (*penv)->GetByteArrayRegion(penv, jmsg32, 0, 32, (jbyte*)msg32); + } + + if (jkeyaggcache != NULL) { + size = (*penv)->GetArrayLength(penv, jkeyaggcache); + CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, size, (jbyte*)keyaggcache.data); + } + + if (jextra_input32 != NULL) { + size = (*penv)->GetArrayLength(penv, jextra_input32); + CHECKRESULT(size != 32, "invalid extra input size"); + (*penv)->GetByteArrayRegion(penv, jextra_input32, 0, 32, (jbyte*)extra_input32); + } + + result = secp256k1_musig_nonce_gen_counter(ctx, &secnonce, &pubnonce, jcounter, + &keypair, + jmsg32 == NULL ? NULL : msg32, jkeyaggcache == NULL ? NULL : &keyaggcache, jextra_input32 == NULL ? NULL : extra_input32); + CHECKRESULT(!result, "secp256k1_musig_nonce_gen failed"); + + 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)); + (*penv)->SetByteArrayRegion(penv, jnonce, 0, sizeof(nonce), (const jbyte*)nonce); + return jnonce; } -static void free_nonces(secp256k1_musig_pubnonce **nonces, size_t count) +static void free_nonces(secp256k1_musig_pubnonce** nonces, size_t count) { - size_t i; - if (nonces == NULL) return; - for (i = 0; i < count; i++) - { - if (nonces[i] != NULL) - free(nonces[i]); - } - free(nonces); + size_t i; + if (nonces == NULL) return; + for (i = 0; i < count; i++) { + if (nonces[i] != NULL) + free(nonces[i]); + } + free(nonces); } /* @@ -886,51 +865,49 @@ static void free_nonces(secp256k1_musig_pubnonce **nonces, size_t count) * Method: secp256k1_musig_nonce_agg * Signature: (J[[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1agg(JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jnonces) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1agg(JNIEnv* penv, jclass clazz, jlong jctx, jobjectArray jnonces) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte in66[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; - secp256k1_musig_pubnonce **pubnonces; - secp256k1_musig_aggnonce combined; - jbyteArray jnonce; - size_t size, count; - size_t i; - int result = 0; - - if (jctx == 0) return NULL; - if (jnonces == NULL) return NULL; - - count = (*penv)->GetArrayLength(penv, jnonces); - CHECKRESULT(count == 0, "public nonces count cannot be 0"); - for (i = 0; i < count; i++) - { - jnonce = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jnonces, i); - size = (*penv)->GetArrayLength(penv, jnonce); - CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size"); - } - - pubnonces = calloc(count, sizeof(secp256k1_musig_pubnonce *)); - CHECKRESULT(pubnonces == NULL, "memory allocation error"); - - for (i = 0; i < count; i++) - { - pubnonces[i] = calloc(1, sizeof(secp256k1_musig_pubnonce)); - CHECKRESULT1(pubnonces[i] == NULL, "memory allocation error", free_nonces(pubnonces, i)); - jnonce = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jnonces, i); - size = fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE; - (*penv)->GetByteArrayRegion(penv, jnonce, 0, size, in66); - result = secp256k1_musig_pubnonce_parse(ctx, pubnonces[i], (unsigned char *)in66); - CHECKRESULT1(!result, "secp256k1_musig_pubnonce_parse failed", free_nonces(pubnonces, i)); - } - result = secp256k1_musig_nonce_agg(ctx, &combined, (const secp256k1_musig_pubnonce *const *)pubnonces, count); - free_nonces(pubnonces, count); - CHECKRESULT(!result, "secp256k1_musig_nonce_agg failed"); - - result = secp256k1_musig_aggnonce_serialize(ctx, (unsigned char *)in66, &combined); - CHECKRESULT(!result, "secp256k1_musig_aggnonce_serialize failed"); - jnonce = (*penv)->NewByteArray(penv, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE); - (*penv)->SetByteArrayRegion(penv, jnonce, 0, size, in66); - return jnonce; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte in66[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; + secp256k1_musig_pubnonce** pubnonces; + secp256k1_musig_aggnonce combined; + jbyteArray jnonce; + size_t size, count; + size_t i; + int result = 0; + + if (jctx == 0) return NULL; + if (jnonces == NULL) return NULL; + + count = (*penv)->GetArrayLength(penv, jnonces); + CHECKRESULT(count == 0, "public nonces count cannot be 0"); + for (i = 0; i < count; i++) { + jnonce = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jnonces, i); + size = (*penv)->GetArrayLength(penv, jnonce); + CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size"); + } + + pubnonces = calloc(count, sizeof(secp256k1_musig_pubnonce*)); + CHECKRESULT(pubnonces == NULL, "memory allocation error"); + + for (i = 0; i < count; i++) { + pubnonces[i] = calloc(1, sizeof(secp256k1_musig_pubnonce)); + CHECKRESULT1(pubnonces[i] == NULL, "memory allocation error", free_nonces(pubnonces, count)); + jnonce = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jnonces, i); + size = fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE; + (*penv)->GetByteArrayRegion(penv, jnonce, 0, size, in66); + result = secp256k1_musig_pubnonce_parse(ctx, pubnonces[i], (unsigned char*)in66); + CHECKRESULT1(!result, "secp256k1_musig_pubnonce_parse failed", free_nonces(pubnonces, count)); + } + result = secp256k1_musig_nonce_agg(ctx, &combined, (const secp256k1_musig_pubnonce* const*)pubnonces, count); + free_nonces(pubnonces, count); + CHECKRESULT(!result, "secp256k1_musig_nonce_agg failed"); + + result = secp256k1_musig_aggnonce_serialize(ctx, (unsigned char*)in66, &combined); + CHECKRESULT(!result, "secp256k1_musig_aggnonce_serialize failed"); + jnonce = (*penv)->NewByteArray(penv, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE); + (*penv)->SetByteArrayRegion(penv, jnonce, 0, size, in66); + return jnonce; } /* @@ -938,63 +915,59 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_musig_pubkey_agg * Signature: (J[[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1agg(JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jpubkeys, jbyteArray jkeyaggcache) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1agg(JNIEnv* penv, jclass clazz, jlong jctx, jobjectArray jpubkeys, jbyteArray jkeyaggcache) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte pub[65]; - secp256k1_pubkey **pubkeys; - secp256k1_xonly_pubkey combined; - secp256k1_musig_keyagg_cache keyaggcache; - jbyteArray jpubkey; - size_t size, count; - size_t i; - int result = 0; - - if (jctx == 0) return NULL; - if (jpubkeys == NULL) return NULL; - count = (*penv)->GetArrayLength(penv, jpubkeys); - CHECKRESULT(count == 0, "pubkeys count cannot be 0"); - for (i = 0; i < count; i++) - { - jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i); - size = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); - } - - if (jkeyaggcache != NULL) - { - size = (*penv)->GetArrayLength(penv, jkeyaggcache); - CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, size, keyaggcache.data); - } - - pubkeys = calloc(count, sizeof(secp256k1_pubkey *)); - CHECKRESULT(pubkeys == NULL, "memory allocation error"); - - for (i = 0; i < count; i++) - { - pubkeys[i] = calloc(1, sizeof(secp256k1_pubkey)); - CHECKRESULT1(pubkeys[i] == NULL, "memory allocation error", free_pubkeys(pubkeys, i)); - jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i); - size = (*penv)->GetArrayLength(penv, jpubkey); - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); - result = secp256k1_ec_pubkey_parse(ctx, pubkeys[i], (unsigned char *)pub, size); - CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(pubkeys, i)); - } - result = secp256k1_musig_pubkey_agg(ctx, &combined, jkeyaggcache == NULL ? NULL : &keyaggcache, (const secp256k1_pubkey *const *)pubkeys, count); - free_pubkeys(pubkeys, count); - CHECKRESULT(!result, "secp256k1_musig_pubkey_agg failed"); - result = secp256k1_xonly_pubkey_serialize(ctx, (unsigned char *)pub, &combined); - CHECKRESULT(!result, "secp256k1_xonly_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 32); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 32, pub); - - if (jkeyaggcache != NULL) - { - (*penv)->SetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (const jbyte*)keyaggcache.data); - } - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte pub[65]; + secp256k1_pubkey** pubkeys; + secp256k1_xonly_pubkey combined; + secp256k1_musig_keyagg_cache keyaggcache; + jbyteArray jpubkey; + size_t size, count; + size_t i; + int result = 0; + + if (jctx == 0) return NULL; + if (jpubkeys == NULL) return NULL; + count = (*penv)->GetArrayLength(penv, jpubkeys); + CHECKRESULT(count == 0, "pubkeys count cannot be 0"); + for (i = 0; i < count; i++) { + jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i); + size = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT((size != 33) && (size != 65), "invalid public key size"); + } + + if (jkeyaggcache != NULL) { + size = (*penv)->GetArrayLength(penv, jkeyaggcache); + CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, size, (jbyte*)keyaggcache.data); + } + + pubkeys = calloc(count, sizeof(secp256k1_pubkey*)); + CHECKRESULT(pubkeys == NULL, "memory allocation error"); + + for (i = 0; i < count; i++) { + pubkeys[i] = calloc(1, sizeof(secp256k1_pubkey)); + CHECKRESULT1(pubkeys[i] == NULL, "memory allocation error", free_pubkeys(pubkeys, count)); + jpubkey = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpubkeys, i); + size = (*penv)->GetArrayLength(penv, jpubkey); + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, size, pub); + result = secp256k1_ec_pubkey_parse(ctx, pubkeys[i], (unsigned char*)pub, size); + CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(pubkeys, count)); + } + result = secp256k1_musig_pubkey_agg(ctx, &combined, jkeyaggcache == NULL ? NULL : &keyaggcache, (const secp256k1_pubkey* const*)pubkeys, count); + free_pubkeys(pubkeys, count); + CHECKRESULT(!result, "secp256k1_musig_pubkey_agg failed"); + result = secp256k1_xonly_pubkey_serialize(ctx, (unsigned char*)pub, &combined); + CHECKRESULT(!result, "secp256k1_xonly_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 32); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 32, pub); + + if (jkeyaggcache != NULL) { + (*penv)->SetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (const jbyte*)keyaggcache.data); + } + return jpubkey; } /* @@ -1002,39 +975,39 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_musig_pubkey_ec_tweak_add * Signature: (J[B[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1ec_1tweak_1add(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jkeyaggcache, jbyteArray jtweak32) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1ec_1tweak_1add(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jkeyaggcache, jbyteArray jtweak32) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte tweak32[32], pub[65]; - secp256k1_pubkey pubkey; - secp256k1_musig_keyagg_cache keyaggcache; - jbyteArray jpubkey; - size_t size; - int result = 0; - - if (jctx == 0) return NULL; - if (jkeyaggcache == NULL) return NULL; - size = (*penv)->GetArrayLength(penv, jkeyaggcache); - CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte tweak32[32], pub[65]; + secp256k1_pubkey pubkey; + secp256k1_musig_keyagg_cache keyaggcache; + jbyteArray jpubkey; + size_t size; + int result = 0; + + if (jctx == 0) return NULL; + if (jkeyaggcache == NULL) return NULL; + size = (*penv)->GetArrayLength(penv, jkeyaggcache); + CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); - if (jtweak32 == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jtweak32) != 32, "tweak must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jtweak32, 0, 32, tweak32); + if (jtweak32 == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jtweak32) != 32, "tweak must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jtweak32, 0, 32, tweak32); - result = secp256k1_musig_pubkey_ec_tweak_add(ctx, &pubkey, &keyaggcache, (const unsigned char*)tweak32); - CHECKRESULT(!result, "secp256k1_musig_pubkey_ec_tweak_add failed"); + result = secp256k1_musig_pubkey_ec_tweak_add(ctx, &pubkey, &keyaggcache, (const unsigned char*)tweak32); + CHECKRESULT(!result, "secp256k1_musig_pubkey_ec_tweak_add failed"); - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); - (*penv)->SetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (const jbyte*)keyaggcache.data); + (*penv)->SetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (const jbyte*)keyaggcache.data); - return jpubkey; + return jpubkey; } /* @@ -1042,39 +1015,39 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_musig_pubkey_xonly_tweak_add * Signature: (J[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1xonly_1tweak_1add(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jkeyaggcache, jbyteArray jtweak32) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1xonly_1tweak_1add(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jkeyaggcache, jbyteArray jtweak32) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - jbyte tweak32[32], pub[65]; - secp256k1_pubkey pubkey; - secp256k1_musig_keyagg_cache keyaggcache; - jbyteArray jpubkey; - size_t size; - int result = 0; - - if (jctx == 0) return NULL; - if (jkeyaggcache == NULL) return NULL; - size = (*penv)->GetArrayLength(penv, jkeyaggcache); - CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); - - if (jtweak32 == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jtweak32) != 32, "tweak must be 32 bytes"); - (*penv)->GetByteArrayRegion(penv, jtweak32, 0, 32, tweak32); - - result = secp256k1_musig_pubkey_xonly_tweak_add(ctx, &pubkey, &keyaggcache, (const unsigned char*)tweak32); - CHECKRESULT(!result, "secp256k1_musig_pubkey_xonly_tweak_add failed"); - - size = 65; - result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); - CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); - - jpubkey = (*penv)->NewByteArray(penv, 65); - (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); - - (*penv)->SetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (const jbyte*)keyaggcache.data); - - return jpubkey; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + jbyte tweak32[32], pub[65]; + secp256k1_pubkey pubkey; + secp256k1_musig_keyagg_cache keyaggcache; + jbyteArray jpubkey; + size_t size; + int result = 0; + + if (jctx == 0) return NULL; + if (jkeyaggcache == NULL) return NULL; + size = (*penv)->GetArrayLength(penv, jkeyaggcache); + CHECKRESULT(size != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); + + if (jtweak32 == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jtweak32) != 32, "tweak must be 32 bytes"); + (*penv)->GetByteArrayRegion(penv, jtweak32, 0, 32, tweak32); + + result = secp256k1_musig_pubkey_xonly_tweak_add(ctx, &pubkey, &keyaggcache, (const unsigned char*)tweak32); + CHECKRESULT(!result, "secp256k1_musig_pubkey_xonly_tweak_add failed"); + + size = 65; + result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed"); + + jpubkey = (*penv)->NewByteArray(penv, 65); + (*penv)->SetByteArrayRegion(penv, jpubkey, 0, 65, pub); + + (*penv)->SetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (const jbyte*)keyaggcache.data); + + return jpubkey; } /* @@ -1082,39 +1055,39 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_musig_nonce_process * Signature: (J[B[B[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1process(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jaggnonce, jbyteArray jmsg32, jbyteArray jkeyaggcache) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1process(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jaggnonce, jbyteArray jmsg32, jbyteArray jkeyaggcache) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - secp256k1_musig_keyagg_cache keyaggcache; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - unsigned char msg32[32]; - jbyteArray jsession; - jbyte buffer[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; - int result = 0; - - if (jctx == 0) return NULL; - if (jaggnonce == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jaggnonce) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid nonce size"); - if (jmsg32 == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jmsg32) != 32, "invalid message size"); - if (jkeyaggcache == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jkeyaggcache) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); - - (*penv)->GetByteArrayRegion(penv, jaggnonce, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, buffer); - result = secp256k1_musig_aggnonce_parse(ctx, &aggnonce, (const unsigned char*)buffer); - CHECKRESULT(!result, "secp256k1_musig_aggnonce_parse failed"); - - (*penv)->GetByteArrayRegion(penv, jmsg32, 0, 32, msg32); - - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); - - result = secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg32, &keyaggcache); - CHECKRESULT(!result, "secp256k1_musig_nonce_process failed"); - - jsession = (*penv)->NewByteArray(penv, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE); - (*penv)->SetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (const jbyte*)session.data); - return jsession; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + secp256k1_musig_keyagg_cache keyaggcache; + secp256k1_musig_aggnonce aggnonce; + secp256k1_musig_session session; + unsigned char msg32[32]; + jbyteArray jsession; + jbyte buffer[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; + int result = 0; + + if (jctx == 0) return NULL; + if (jaggnonce == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jaggnonce) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid nonce size"); + if (jmsg32 == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jmsg32) != 32, "invalid message size"); + if (jkeyaggcache == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jkeyaggcache) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid keyagg cache size"); + + (*penv)->GetByteArrayRegion(penv, jaggnonce, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, buffer); + result = secp256k1_musig_aggnonce_parse(ctx, &aggnonce, (const unsigned char*)buffer); + CHECKRESULT(!result, "secp256k1_musig_aggnonce_parse failed"); + + (*penv)->GetByteArrayRegion(penv, jmsg32, 0, 32, (jbyte*)msg32); + + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); + + result = secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg32, &keyaggcache); + CHECKRESULT(!result, "secp256k1_musig_nonce_process failed"); + + jsession = (*penv)->NewByteArray(penv, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE); + (*penv)->SetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (const jbyte*)session.data); + return jsession; } /* @@ -1122,48 +1095,48 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_musig_partial_sign * Signature: (J[B[B[B[B[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1partial_1sign(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsecnonce, jbyteArray jprivkey, jbyteArray jkeyaggcache, jbyteArray jsession) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1partial_1sign(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsecnonce, jbyteArray jprivkey, jbyteArray jkeyaggcache, jbyteArray jsession) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - secp256k1_musig_partial_sig psig; - secp256k1_musig_secnonce secnonce; - unsigned char seckey[32], sig[32]; - secp256k1_keypair keypair; - secp256k1_musig_keyagg_cache keyaggcache; - secp256k1_musig_session session; - jbyteArray jpsig; - int result = 0; - - if (jctx == 0) return NULL; - if (jsecnonce == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jsecnonce) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE, "invalid secret nonce size"); - if (jprivkey == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jprivkey) != 32, "invalid private key size"); - if (jkeyaggcache == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jkeyaggcache) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid cache size"); - if (jsession == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jsession) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, "invalid session size"); - - - (*penv)->GetByteArrayRegion(penv, jsecnonce, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE, (jbyte*)secnonce.data); - - (*penv)->GetByteArrayRegion(penv, jprivkey, 0, 32, seckey); - result = secp256k1_keypair_create(ctx, &keypair, seckey); - CHECKRESULT(!result, "secp256k1_keypair_create failed"); - - - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); - (*penv)->GetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (jbyte*)session.data); - - result = secp256k1_musig_partial_sign(ctx, &psig, &secnonce, &keypair, &keyaggcache, &session); - CHECKRESULT(!result, "secp256k1_musig_partial_sign failed"); - - result = secp256k1_musig_partial_sig_serialize(ctx, sig, &psig); - CHECKRESULT(!result, "secp256k1_musig_partial_sig_serialize failed"); - - jpsig = (*penv)->NewByteArray(penv, 32); - (*penv)->SetByteArrayRegion(penv, jpsig, 0, 32, sig); - return jpsig; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + secp256k1_musig_partial_sig psig; + secp256k1_musig_secnonce secnonce; + unsigned char seckey[32], sig[32]; + secp256k1_keypair keypair; + secp256k1_musig_keyagg_cache keyaggcache; + secp256k1_musig_session session; + jbyteArray jpsig; + int result = 0; + + if (jctx == 0) return NULL; + if (jsecnonce == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jsecnonce) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE, "invalid secret nonce size"); + if (jprivkey == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jprivkey) != 32, "invalid private key size"); + if (jkeyaggcache == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jkeyaggcache) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid cache size"); + if (jsession == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jsession) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, "invalid session size"); + + + (*penv)->GetByteArrayRegion(penv, jsecnonce, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE, (jbyte*)secnonce.data); + + (*penv)->GetByteArrayRegion(penv, jprivkey, 0, 32, (jbyte*)seckey); + result = secp256k1_keypair_create(ctx, &keypair, seckey); + CHECKRESULT(!result, "secp256k1_keypair_create failed"); + + + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); + (*penv)->GetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (jbyte*)session.data); + + result = secp256k1_musig_partial_sign(ctx, &psig, &secnonce, &keypair, &keyaggcache, &session); + CHECKRESULT(!result, "secp256k1_musig_partial_sign failed"); + + result = secp256k1_musig_partial_sig_serialize(ctx, sig, &psig); + CHECKRESULT(!result, "secp256k1_musig_partial_sig_serialize failed"); + + jpsig = (*penv)->NewByteArray(penv, 32); + (*penv)->SetByteArrayRegion(penv, jpsig, 0, 32, (const jbyte*)sig); + return jpsig; } /* @@ -1171,67 +1144,66 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256 * Method: secp256k1_musig_partial_sig_verify * Signature: (J[B[B[B[B[B)I */ -JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1partial_1sig_1verify(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpsig, jbyteArray jpubnonce, jbyteArray jpubkey, jbyteArray jkeyaggcache, jbyteArray jsession) +JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1partial_1sig_1verify(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jpsig, jbyteArray jpubnonce, jbyteArray jpubkey, jbyteArray jkeyaggcache, jbyteArray jsession) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - secp256k1_musig_partial_sig psig; - secp256k1_musig_pubnonce pubnonce; - secp256k1_pubkey pubkey; - jsize pubkeySize; - secp256k1_musig_keyagg_cache keyaggcache; - secp256k1_musig_session session; - // we use the same buffer to copy a partial sig, a nonce and a pubkey, largest size is a nonce - jbyte buffer[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; - int result = 0; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + secp256k1_musig_partial_sig psig; + secp256k1_musig_pubnonce pubnonce; + secp256k1_pubkey pubkey; + jsize pubkeySize; + secp256k1_musig_keyagg_cache keyaggcache; + secp256k1_musig_session session; + // we use the same buffer to copy a partial sig, a nonce and a pubkey, largest size is a nonce + jbyte buffer[fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE]; + int result = 0; - if (jctx == 0) return 0; + if (jctx == 0) return 0; - if (jpsig == NULL) return 0; - CHECKRESULT((*penv)->GetArrayLength(penv, jpsig) != 32, "invalid partial signature size"); + if (jpsig == NULL) return 0; + CHECKRESULT((*penv)->GetArrayLength(penv, jpsig) != 32, "invalid partial signature size"); - if (jpubnonce == NULL) return 0; - CHECKRESULT((*penv)->GetArrayLength(penv, jpubnonce) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size"); + if (jpubnonce == NULL) return 0; + CHECKRESULT((*penv)->GetArrayLength(penv, jpubnonce) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, "invalid public nonce size"); - if (jpubkey == NULL) return 0; - pubkeySize = (*penv)->GetArrayLength(penv, jpubkey); - CHECKRESULT(pubkeySize != 33 && pubkeySize != 65, "invalid public key size"); + if (jpubkey == NULL) return 0; + pubkeySize = (*penv)->GetArrayLength(penv, jpubkey); + CHECKRESULT(pubkeySize != 33 && pubkeySize != 65, "invalid public key size"); - if (jkeyaggcache == NULL) return 0; - CHECKRESULT((*penv)->GetArrayLength(penv, jkeyaggcache) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid cache size"); + if (jkeyaggcache == NULL) return 0; + CHECKRESULT((*penv)->GetArrayLength(penv, jkeyaggcache) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, "invalid cache size"); - if (jsession == NULL) return 0; - CHECKRESULT((*penv)->GetArrayLength(penv, jsession) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, "invalid session size"); + if (jsession == NULL) return 0; + CHECKRESULT((*penv)->GetArrayLength(penv, jsession) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, "invalid session size"); - (*penv)->GetByteArrayRegion(penv, jpsig, 0, 32, buffer); - result = secp256k1_musig_partial_sig_parse(ctx, &psig, (const unsigned char*)buffer); - CHECKRESULT(!result, "secp256k1_musig_partial_sig_parse failed"); + (*penv)->GetByteArrayRegion(penv, jpsig, 0, 32, buffer); + result = secp256k1_musig_partial_sig_parse(ctx, &psig, (const unsigned char*)buffer); + CHECKRESULT(!result, "secp256k1_musig_partial_sig_parse failed"); - (*penv)->GetByteArrayRegion(penv, jpubnonce, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, buffer); - result = secp256k1_musig_pubnonce_parse(ctx, &pubnonce, (const unsigned char*)buffer); - CHECKRESULT(!result, "secp256k1_musig_pubnonce_parse failed"); + (*penv)->GetByteArrayRegion(penv, jpubnonce, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE, buffer); + result = secp256k1_musig_pubnonce_parse(ctx, &pubnonce, (const unsigned char*)buffer); + CHECKRESULT(!result, "secp256k1_musig_pubnonce_parse failed"); - (*penv)->GetByteArrayRegion(penv, jpubkey, 0, pubkeySize, buffer); - result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (const unsigned char*)buffer, pubkeySize); - CHECKRESULT(!result, "secp256k1_musig_pubkey_parse failed"); + (*penv)->GetByteArrayRegion(penv, jpubkey, 0, pubkeySize, buffer); + result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (const unsigned char*)buffer, pubkeySize); + CHECKRESULT(!result, "secp256k1_musig_pubkey_parse failed"); - (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); - (*penv)->GetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (jbyte*)session.data); + (*penv)->GetByteArrayRegion(penv, jkeyaggcache, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE, (jbyte*)keyaggcache.data); + (*penv)->GetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (jbyte*)session.data); - result = secp256k1_musig_partial_sig_verify(ctx, &psig, &pubnonce, &pubkey, &keyaggcache, &session); + result = secp256k1_musig_partial_sig_verify(ctx, &psig, &pubnonce, &pubkey, &keyaggcache, &session); - return result; + return result; } -static void free_partial_sigs(secp256k1_musig_partial_sig **psigs, size_t count) +static void free_partial_sigs(secp256k1_musig_partial_sig** psigs, size_t count) { - size_t i; - if (psigs == NULL) return; - for (i = 0; i < count; i++) - { - if (psigs[i] != NULL) - free(psigs[i]); - } - free(psigs); + size_t i; + if (psigs == NULL) return; + for (i = 0; i < count; i++) { + if (psigs[i] != NULL) + free(psigs[i]); + } + free(psigs); } /* @@ -1239,45 +1211,44 @@ static void free_partial_sigs(secp256k1_musig_partial_sig **psigs, size_t count) * Method: secp256k1_musig_partial_sig_agg * Signature: (J[B[[B)[B */ -JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1partial_1sig_1agg(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsession, jobjectArray jpsigs) +JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1partial_1sig_1agg(JNIEnv* penv, jclass clazz, jlong jctx, jbyteArray jsession, jobjectArray jpsigs) { - const secp256k1_context *ctx = (const secp256k1_context *)jctx; - secp256k1_musig_session session; - secp256k1_musig_partial_sig **psigs; - unsigned char sig64[64]; - jbyteArray jpsig; - size_t size, count; - size_t i; - int result = 0; - - if (jctx == 0) return NULL; - if (jsession == NULL) return NULL; - CHECKRESULT((*penv)->GetArrayLength(penv, jsession) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, "invalid session size"); - (*penv)->GetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (jbyte*)session.data); - - if (jpsigs == NULL) return NULL; - count = (*penv)->GetArrayLength(penv, jpsigs); - CHECKRESULT(count == 0, "partial sigs count cannot be 0"); - - psigs = calloc(count, sizeof(secp256k1_musig_partial_sig *)); - CHECKRESULT(psigs == NULL, "memory allocation error"); - - for (i = 0; i < count; i++) - { - psigs[i] = calloc(1, sizeof(secp256k1_musig_partial_sig)); - CHECKRESULT1(psigs[i] == NULL, "memory allocation error", free_partial_sigs(psigs, i)); - jpsig = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpsigs, i); - size = (*penv)->GetArrayLength(penv, jpsig); - CHECKRESULT1(size != 32, "invalid partial signature size", free_partial_sigs(psigs, i)); - (*penv)->GetByteArrayRegion(penv, jpsig, 0, 32, (jbyte*)sig64); - result = secp256k1_musig_partial_sig_parse(ctx, psigs[i], sig64); - CHECKRESULT1(!result, "secp256k1_musig_partial_sig_parse failed", free_partial_sigs(psigs, i)); - } - result = secp256k1_musig_partial_sig_agg(ctx, sig64, &session, (const secp256k1_musig_partial_sig *const *)psigs, count); - free_partial_sigs(psigs, count); - CHECKRESULT(!result, "secp256k1_musig_pubkey_agg failed"); - - jpsig = (*penv)->NewByteArray(penv, 64); - (*penv)->SetByteArrayRegion(penv, jpsig, 0, 64, (const jbyte*)sig64); - return jpsig; + const secp256k1_context* ctx = (const secp256k1_context*)jctx; + secp256k1_musig_session session; + secp256k1_musig_partial_sig** psigs; + unsigned char sig64[64]; + jbyteArray jpsig; + size_t size, count; + size_t i; + int result = 0; + + if (jctx == 0) return NULL; + if (jsession == NULL) return NULL; + CHECKRESULT((*penv)->GetArrayLength(penv, jsession) != fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, "invalid session size"); + (*penv)->GetByteArrayRegion(penv, jsession, 0, fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE, (jbyte*)session.data); + + if (jpsigs == NULL) return NULL; + count = (*penv)->GetArrayLength(penv, jpsigs); + CHECKRESULT(count == 0, "partial sigs count cannot be 0"); + + psigs = calloc(count, sizeof(secp256k1_musig_partial_sig*)); + CHECKRESULT(psigs == NULL, "memory allocation error"); + + for (i = 0; i < count; i++) { + psigs[i] = calloc(1, sizeof(secp256k1_musig_partial_sig)); + CHECKRESULT1(psigs[i] == NULL, "memory allocation error", free_partial_sigs(psigs, count)); + jpsig = (jbyteArray)(*penv)->GetObjectArrayElement(penv, jpsigs, i); + size = (*penv)->GetArrayLength(penv, jpsig); + CHECKRESULT1(size != 32, "invalid partial signature size", free_partial_sigs(psigs, count)); + (*penv)->GetByteArrayRegion(penv, jpsig, 0, 32, (jbyte*)sig64); + result = secp256k1_musig_partial_sig_parse(ctx, psigs[i], sig64); + CHECKRESULT1(!result, "secp256k1_musig_partial_sig_parse failed", free_partial_sigs(psigs, count)); + } + result = secp256k1_musig_partial_sig_agg(ctx, sig64, &session, (const secp256k1_musig_partial_sig* const*)psigs, count); + free_partial_sigs(psigs, count); + CHECKRESULT(!result, "secp256k1_musig_pubkey_agg failed"); + + jpsig = (*penv)->NewByteArray(penv, 64); + (*penv)->SetByteArrayRegion(penv, jpsig, 0, 64, (const jbyte*)sig64); + return jpsig; } diff --git a/jni/jvm/all/build.gradle.kts b/jni/jvm/all/build.gradle.kts index dd98017..1003b49 100644 --- a/jni/jvm/all/build.gradle.kts +++ b/jni/jvm/all/build.gradle.kts @@ -1,3 +1,5 @@ +import org.gradle.kotlin.dsl.register + plugins { `java-library` id("org.jetbrains.dokka") @@ -15,7 +17,7 @@ publishing { create("jvm") { artifactId = "secp256k1-kmp-jni-jvm" from(components["java"]) - val sourcesJar = task("sourcesJar") { + val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") } artifact(sourcesJar) diff --git a/jni/jvm/build.gradle.kts b/jni/jvm/build.gradle.kts index f16930f..53c8903 100644 --- a/jni/jvm/build.gradle.kts +++ b/jni/jvm/build.gradle.kts @@ -1,3 +1,4 @@ +import org.gradle.kotlin.dsl.register import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -9,7 +10,8 @@ plugins { val currentOs = org.gradle.internal.os.OperatingSystem.current() val bash = if (currentOs.isWindows) "bash.exe" else "bash" -val buildNativeHost by tasks.creating(Exec::class) { +val buildNativeHost by tasks.registering(Exec::class) { + -> group = "build" dependsOn(":jni:generateHeaders") dependsOn(":native:buildSecp256k1Host") @@ -51,7 +53,7 @@ publishing { create("jvm") { artifactId = "secp256k1-kmp-jni-jvm-extract" from(components["java"]) - val sourcesJar = task("sourcesJar") { + val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") } artifact(sourcesJar) diff --git a/jni/jvm/darwin/build.gradle.kts b/jni/jvm/darwin/build.gradle.kts index 9d20d31..cec3d6f 100644 --- a/jni/jvm/darwin/build.gradle.kts +++ b/jni/jvm/darwin/build.gradle.kts @@ -1,3 +1,4 @@ +import org.gradle.kotlin.dsl.register import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -24,7 +25,8 @@ dependencies { implementation(project(":jni:jvm")) } -val copyJni by tasks.creating(Sync::class) { +val copyJni by tasks.registering(Sync::class) { + -> onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX } dependsOn(":jni:jvm:buildNativeHost") from(rootDir.resolve("jni/jvm/build/darwin/libsecp256k1-jni.dylib")) @@ -42,7 +44,7 @@ publishing { val pub = create("jvm") { artifactId = "secp256k1-kmp-jni-jvm-darwin" from(components["java"]) - val sourcesJar = task("sourcesJar") { + val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") } artifact(sourcesJar) diff --git a/jni/jvm/linux/build.gradle.kts b/jni/jvm/linux/build.gradle.kts index e2548ad..b80c5fe 100644 --- a/jni/jvm/linux/build.gradle.kts +++ b/jni/jvm/linux/build.gradle.kts @@ -1,3 +1,4 @@ +import org.gradle.kotlin.dsl.register import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -23,7 +24,8 @@ dependencies { implementation(project(":jni:jvm")) } -val copyJni by tasks.creating(Sync::class) { +val copyJni by tasks.registering(Sync::class) { + -> onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux } dependsOn(":jni:jvm:buildNativeHost") from(rootDir.resolve("jni/jvm/build/linux/libsecp256k1-jni.so")) @@ -41,7 +43,7 @@ publishing { val pub = create("jvm") { artifactId = "secp256k1-kmp-jni-jvm-linux" from(components["java"]) - val sourcesJar = task("sourcesJar") { + val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") } artifact(sourcesJar) diff --git a/jni/jvm/mingw/build.gradle.kts b/jni/jvm/mingw/build.gradle.kts index a867cb2..a88afbd 100644 --- a/jni/jvm/mingw/build.gradle.kts +++ b/jni/jvm/mingw/build.gradle.kts @@ -1,3 +1,5 @@ +import org.gradle.kotlin.dsl.register + plugins { kotlin("jvm") id("org.jetbrains.dokka") @@ -8,7 +10,8 @@ dependencies { implementation(project(":jni:jvm")) } -val copyJni by tasks.creating(Sync::class) { +val copyJni by tasks.registering(Sync::class) { + -> onlyIf { org.gradle.internal.os.OperatingSystem.current().isWindows } dependsOn(":jni:jvm:buildNativeHost") from(rootDir.resolve("jni/jvm/build/mingw/secp256k1-jni.dll")) @@ -26,7 +29,7 @@ publishing { val pub = create("jvm") { artifactId = "secp256k1-kmp-jni-jvm-mingw" from(components["java"]) - val sourcesJar = task("sourcesJar") { + val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") } artifact(sourcesJar) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index b7881d1..8c439d6 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -1,3 +1,4 @@ +import com.android.build.gradle.LibraryExtension import org.gradle.internal.os.OperatingSystem val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true @@ -9,11 +10,13 @@ if (includeAndroid) { val currentOs = OperatingSystem.current() val bash = "bash" -val buildSecp256k1 by tasks.creating { group = "build" } +val buildSecp256k1 = tasks.register("buildSecp256k1") { + group = "build" + dependsOn("buildSecp256k1Host") +} -val buildSecp256k1Host by tasks.creating(Exec::class) { +tasks.register("buildSecp256k1Host") { group = "build" - buildSecp256k1.dependsOn(this) val target = when { currentOs.isLinux -> "linux" @@ -30,10 +33,10 @@ val buildSecp256k1Host by tasks.creating(Exec::class) { commandLine(bash, "-l", "build.sh") } + // specific build task for linux arm64, which is cross-compiled on a linux x64 host -val buildSecp256k1LinuxArm64 by tasks.creating(Exec::class) { +tasks.register("buildSecp256k1LinuxArm64") { group = "build" - buildSecp256k1.dependsOn(this) val target = "linuxArm64" @@ -45,9 +48,8 @@ val buildSecp256k1LinuxArm64 by tasks.creating(Exec::class) { commandLine(bash, "-l", "build.sh") } -val buildSecp256k1Ios by tasks.creating(Exec::class) { +tasks.register("buildSecp256k1Ios") { group = "build" - buildSecp256k1.dependsOn(this) onlyIf { currentOs.isMacOsX } @@ -59,15 +61,18 @@ val buildSecp256k1Ios by tasks.creating(Exec::class) { } if (includeAndroid) { - - val buildSecp256k1Android by tasks.creating { + tasks.register("buildSecp256k1Android") { group = "build" - buildSecp256k1.dependsOn(this) + dependsOn("buildSecp256k1Androidx86_64") + dependsOn("buildSecp256k1Androidx86") + dependsOn("buildSecp256k1Androidarm64-v8a") + dependsOn("buildSecp256k1Androidarmeabi-v7a") } - fun creatingBuildSecp256k1Android(arch: String) = tasks.creating(Exec::class) { + buildSecp256k1 { dependsOn("buildSecp256k1Android") } + + fun createBuildSecp256k1Android(arch: String) = tasks.register("buildSecp256k1Android$arch") { group = "build" - buildSecp256k1Android.dependsOn(this) inputs.files(projectDir.resolve("build-android.sh")) outputs.dir(projectDir.resolve("build/android/$arch")) @@ -82,17 +87,17 @@ if (includeAndroid) { } environment("TOOLCHAIN", toolchain) environment("ARCH", arch) - environment("ANDROID_NDK", (project(":jni:android").extensions["android"] as com.android.build.gradle.LibraryExtension).ndkDirectory) + environment("ANDROID_NDK", (project(":jni:android").extensions["android"] as LibraryExtension).ndkDirectory) commandLine(bash, "build-android.sh") } - val buildSecp256k1AndroidX86_64 by creatingBuildSecp256k1Android("x86_64") - val buildSecp256k1AndroidX86 by creatingBuildSecp256k1Android("x86") - val buildSecp256k1AndroidArm64v8a by creatingBuildSecp256k1Android("arm64-v8a") - val buildSecp256k1AndroidArmeabiv7a by creatingBuildSecp256k1Android("armeabi-v7a") + createBuildSecp256k1Android("x86_64") + createBuildSecp256k1Android("x86") + createBuildSecp256k1Android("arm64-v8a") + createBuildSecp256k1Android("armeabi-v7a") } -val clean by tasks.creating { +val clean by tasks.registering { group = "build" doLast { delete(projectDir.resolve("build")) diff --git a/settings.gradle.kts b/settings.gradle.kts index 42fa5f0..beae331 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,7 +6,7 @@ pluginManagement { resolutionStrategy { eachPlugin { if (requested.id.namespace == "com.android" || requested.id.name == "kotlin-android-extensions") { - useModule("com.android.tools.build:gradle:7.3.1") + useModule("com.android.tools.build:gradle:8.13.1") } } } diff --git a/tests/build.gradle.kts b/tests/build.gradle.kts index e343a02..576a025 100644 --- a/tests/build.gradle.kts +++ b/tests/build.gradle.kts @@ -1,4 +1,6 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeHostTest import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest @@ -9,23 +11,21 @@ plugins { id("com.android.library") } } +val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true kotlin { explicitApi() - val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true - - val commonMain by sourceSets.getting { - dependencies { - implementation(rootProject) - } - } - val commonTest by sourceSets.getting { - dependencies { - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) - implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.5.4") - api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") + if (includeAndroid) { + androidTarget { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } + @OptIn(ExperimentalKotlinGradlePluginApi::class) + instrumentedTestVariant { + // This makes instrumented tests depend on commonTest source + sourceSetTree.set(KotlinSourceSetTree.test) + } } } @@ -43,22 +43,37 @@ kotlin { } } - if (includeAndroid) { - androidTarget { - compilerOptions { - jvmTarget.set(JvmTarget.JVM_1_8) + applyDefaultHierarchyTemplate() + + sourceSets { + val commonMain by getting { + dependencies { + implementation(rootProject) } - sourceSets["androidMain"].dependencies { - implementation(project(":jni:android")) + } + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.8.0") + api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") + } + } + if (includeAndroid) { + val androidMain by getting { + dependencies { + implementation(project(":jni:android")) + } } - sourceSets["androidUnitTest"].dependencies { - implementation(kotlin("test-junit")) - implementation("androidx.test.ext:junit:1.1.2") - implementation("androidx.test.espresso:espresso-core:3.3.0") + val androidInstrumentedTest by getting { + dependencies { + implementation(kotlin("test-junit")) + implementation("androidx.test.ext:junit:1.3.0") + implementation("androidx.test.espresso:espresso-core:3.7.0") + } } } } - linuxX64() macosX64() macosArm64() @@ -67,13 +82,12 @@ kotlin { iosSimulatorArm64() } -val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true if (includeAndroid) { extensions.configure("android") { namespace = "fr.acinq.secp256k1.tests" defaultConfig { - compileSdk = 30 + compileSdk = 31 minSdk = 21 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/tests/src/androidInstrumentedTest/assets/musig2/det_sign_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/det_sign_vectors.json new file mode 100644 index 0000000..261669c --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/det_sign_vectors.json @@ -0,0 +1,144 @@ +{ + "sk": "7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671", + "pubkeys": [ + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + "020000000000000000000000000000000000000000000000000000000000000007" + ], + "msgs": [ + "F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF", + "2626262626262626262626262626262626262626262626262626262626262626262626262626" + ], + "valid_test_cases": [ + { + "rand": "0000000000000000000000000000000000000000000000000000000000000000", + "aggothernonce": "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "key_indices": [0, 1, 2], + "tweaks": [], + "is_xonly": [], + "msg_index": 0, + "signer_index": 0, + "expected": [ + "03D96275257C2FCCBB6EEB77BDDF51D3C88C26EE1626C6CDA8999B9D34F4BA13A60309BE2BF883C6ABE907FA822D9CA166D51A3DCC28910C57528F6983FC378B7843", + "41EA65093F71D084785B20DC26A887CD941C9597860A21660CBDB9CC2113CAD3" + ] + }, + { + "rand": null, + "aggothernonce": "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "key_indices": [1, 0, 2], + "tweaks": [], + "is_xonly": [], + "msg_index": 0, + "signer_index": 1, + "expected": [ + "028FBCCF5BB73A7B61B270BAD15C0F9475D577DD85C2157C9D38BEF1EC922B48770253BE3638C87369BC287E446B7F2C8CA5BEB9FFBD1EA082C62913982A65FC214D", + "AEAA31262637BFA88D5606679018A0FEEEC341F3107D1199857F6C81DE61B8DD" + ] + }, + { + "rand": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "aggothernonce": "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "key_indices": [1, 2, 0], + "tweaks": [], + "is_xonly": [], + "msg_index": 1, + "signer_index": 2, + "expected": [ + "024FA8D774F0C8743FAA77AFB4D08EE5A013C2E8EEAD8A6F08A77DDD2D28266DB803050905E8C994477F3F2981861A2E3791EF558626E645FBF5AA131C5D6447C2C2", + "FEE28A56B8556B7632E42A84122C51A4861B1F2DEC7E81B632195E56A52E3E13" + ], + "comment": "Message longer than 32 bytes" + }, + { + "rand": "0000000000000000000000000000000000000000000000000000000000000000", + "aggothernonce": "032DE2662628C90B03F5E720284EB52FF7D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1CA6BEB2090C93D930321071AD40B2F44E599046", + "key_indices": [0, 1, 2], + "tweaks": ["E8F791FF9225A2AF0102AFFF4A9A723D9612A682A25EBE79802B263CDFCD83BB"], + "is_xonly": [true], + "msg_index": 0, + "signer_index": 0, + "expected": [ + "031E07C0D11A0134E55DB1FC16095ADCBD564236194374AA882BFB3C78273BF673039D0336E8CA6288C00BFC1F8B594563529C98661172B9BC1BE85C23A4CE1F616B", + "7B1246C5889E59CB0375FA395CC86AC42D5D7D59FD8EAB4FDF1DCAB2B2F006EA" + ], + "comment": "Tweaked public key" + } + ], + "error_test_cases": [ + { + "rand": "0000000000000000000000000000000000000000000000000000000000000000", + "aggothernonce": "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "key_indices": [1, 0, 3], + "tweaks": [], + "is_xonly": [], + "msg_index": 0, + "signer_index": 1, + "error": { + "type": "invalid_contribution", + "signer": 2, + "contrib": "pubkey" + }, + "comment": "Signer 2 provided an invalid public key" + }, + { + "rand": "0000000000000000000000000000000000000000000000000000000000000000", + "aggothernonce": "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "key_indices": [1, 2], + "tweaks": [], + "is_xonly": [], + "msg_index": 0, + "signer_index": 1, + "error": { + "type": "value", + "message": "The signer's pubkey must be included in the list of pubkeys." + }, + "comment": "The signers pubkey is not in the list of pubkeys" + }, + { + "rand": "0000000000000000000000000000000000000000000000000000000000000000", + "aggothernonce": "0437C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "key_indices": [1, 2, 0], + "tweaks": [], + "is_xonly": [], + "msg_index": 0, + "signer_index": 2, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggothernonce" + }, + "comment": "aggothernonce is invalid due wrong tag, 0x04, in the first half" + }, + { + "rand": "0000000000000000000000000000000000000000000000000000000000000000", + "aggothernonce": "0000000000000000000000000000000000000000000000000000000000000000000287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "key_indices": [1, 2, 0], + "tweaks": [], + "is_xonly": [], + "msg_index": 0, + "signer_index": 2, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggothernonce" + }, + "comment": "aggothernonce is invalid because first half corresponds to point at infinity" + }, + { + "rand": "0000000000000000000000000000000000000000000000000000000000000000", + "aggothernonce": "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "key_indices": [1, 2, 0], + "tweaks": ["FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"], + "is_xonly": [false], + "msg_index": 0, + "signer_index": 2, + "error": { + "type": "value", + "message": "The tweak must be less than n." + }, + "comment": "Tweak is invalid because it exceeds group size" + } + ] +} diff --git a/tests/src/androidInstrumentedTest/assets/musig2/key_agg_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/key_agg_vectors.json new file mode 100644 index 0000000..b2e623d --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/key_agg_vectors.json @@ -0,0 +1,88 @@ +{ + "pubkeys": [ + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66", + "020000000000000000000000000000000000000000000000000000000000000005", + "02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30", + "04F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9" + ], + "tweaks": [ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + "252E4BD67410A76CDF933D30EAA1608214037F1B105A013ECCD3C5C184A6110B" + ], + "valid_test_cases": [ + { + "key_indices": [0, 1, 2], + "expected": "90539EEDE565F5D054F32CC0C220126889ED1E5D193BAF15AEF344FE59D4610C" + }, + { + "key_indices": [2, 1, 0], + "expected": "6204DE8B083426DC6EAF9502D27024D53FC826BF7D2012148A0575435DF54B2B" + }, + { + "key_indices": [0, 0, 0], + "expected": "B436E3BAD62B8CD409969A224731C193D051162D8C5AE8B109306127DA3AA935" + }, + { + "key_indices": [0, 0, 1, 1], + "expected": "69BC22BFA5D106306E48A20679DE1D7389386124D07571D0D872686028C26A3E" + } + ], + "error_test_cases": [ + { + "key_indices": [0, 3], + "tweak_indices": [], + "is_xonly": [], + "error": { + "type": "invalid_contribution", + "signer": 1, + "contrib": "pubkey" + }, + "comment": "Invalid public key" + }, + { + "key_indices": [0, 4], + "tweak_indices": [], + "is_xonly": [], + "error": { + "type": "invalid_contribution", + "signer": 1, + "contrib": "pubkey" + }, + "comment": "Public key exceeds field size" + }, + { + "key_indices": [5, 0], + "tweak_indices": [], + "is_xonly": [], + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubkey" + }, + "comment": "First byte of public key is not 2 or 3" + }, + { + "key_indices": [0, 1], + "tweak_indices": [0], + "is_xonly": [true], + "error": { + "type": "value", + "message": "The tweak must be less than n." + }, + "comment": "Tweak is out of range" + }, + { + "key_indices": [6], + "tweak_indices": [1], + "is_xonly": [false], + "error": { + "type": "value", + "message": "The result of tweaking cannot be infinity." + }, + "comment": "Intermediate tweaking result is point at infinity" + } + ] +} diff --git a/tests/src/androidInstrumentedTest/assets/musig2/key_sort_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/key_sort_vectors.json new file mode 100644 index 0000000..de088a7 --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/key_sort_vectors.json @@ -0,0 +1,18 @@ +{ + "pubkeys": [ + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EFF", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8" + ], + "sorted_pubkeys": [ + "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EFF", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659" + ] +} diff --git a/tests/src/androidInstrumentedTest/assets/musig2/nonce_agg_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/nonce_agg_vectors.json new file mode 100644 index 0000000..1c04b88 --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/nonce_agg_vectors.json @@ -0,0 +1,51 @@ +{ + "pnonces": [ + "020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E66603BA47FBC1834437B3212E89A84D8425E7BF12E0245D98262268EBDCB385D50641", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833", + "020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E6660279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60379BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "04FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B831", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A602FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30" + ], + "valid_test_cases": [ + { + "pnonce_indices": [0, 1], + "expected": "035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B024725377345BDE0E9C33AF3C43C0A29A9249F2F2956FA8CFEB55C8573D0262DC8" + }, + { + "pnonce_indices": [2, 3], + "expected": "035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B000000000000000000000000000000000000000000000000000000000000000000", + "comment": "Sum of second points encoded in the nonces is point at infinity which is serialized as 33 zero bytes" + } + ], + "error_test_cases": [ + { + "pnonce_indices": [0, 4], + "error": { + "type": "invalid_contribution", + "signer": 1, + "contrib": "pubnonce" + }, + "comment": "Public nonce from signer 1 is invalid due wrong tag, 0x04, in the first half" + }, + { + "pnonce_indices": [5, 1], + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubnonce" + }, + "comment": "Public nonce from signer 0 is invalid because the second half does not correspond to an X coordinate" + }, + { + "pnonce_indices": [6, 1], + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubnonce" + }, + "comment": "Public nonce from signer 0 is invalid because second half exceeds field size" + } + ] +} diff --git a/tests/src/androidInstrumentedTest/assets/musig2/nonce_gen_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/nonce_gen_vectors.json new file mode 100644 index 0000000..ced946f --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/nonce_gen_vectors.json @@ -0,0 +1,44 @@ +{ + "test_cases": [ + { + "rand_": "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F", + "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "pk": "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", + "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", + "msg": "0101010101010101010101010101010101010101010101010101010101010101", + "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", + "expected_secnonce": "B114E502BEAA4E301DD08A50264172C84E41650E6CB726B410C0694D59EFFB6495B5CAF28D045B973D63E3C99A44B807BDE375FD6CB39E46DC4A511708D0E9D2024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", + "expected_pubnonce": "02F7BE7089E8376EB355272368766B17E88E7DB72047D05E56AA881EA52B3B35DF02C29C8046FDD0DED4C7E55869137200FBDBFE2EB654267B6D7013602CAED3115A" + }, + { + "rand_": "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F", + "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "pk": "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", + "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", + "msg": "", + "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", + "expected_secnonce": "E862B068500320088138468D47E0E6F147E01B6024244AE45EAC40ACE5929B9F0789E051170B9E705D0B9EB49049A323BBBBB206D8E05C19F46C6228742AA7A9024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", + "expected_pubnonce": "023034FA5E2679F01EE66E12225882A7A48CC66719B1B9D3B6C4DBD743EFEDA2C503F3FD6F01EB3A8E9CB315D73F1F3D287CAFBB44AB321153C6287F407600205109" + }, + { + "rand_": "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F", + "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "pk": "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", + "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", + "msg": "2626262626262626262626262626262626262626262626262626262626262626262626262626", + "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", + "expected_secnonce": "3221975ACBDEA6820EABF02A02B7F27D3A8EF68EE42787B88CBEFD9AA06AF3632EE85B1A61D8EF31126D4663A00DD96E9D1D4959E72D70FE5EBB6E7696EBA66F024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", + "expected_pubnonce": "02E5BBC21C69270F59BD634FCBFA281BE9D76601295345112C58954625BF23793A021307511C79F95D38ACACFF1B4DA98228B77E65AA216AD075E9673286EFB4EAF3" + }, + { + "rand_": "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F", + "sk": null, + "pk": "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "aggpk": null, + "msg": null, + "extra_in": null, + "expected_secnonce": "89BDD787D0284E5E4D5FC572E49E316BAB7E21E3B1830DE37DFE80156FA41A6D0B17AE8D024C53679699A6FD7944D9C4A366B514BAF43088E0708B1023DD289702F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "expected_pubnonce": "02C96E7CB1E8AA5DAC64D872947914198F607D90ECDE5200DE52978AD5DED63C000299EC5117C2D29EDEE8A2092587C3909BE694D5CFF0667D6C02EA4059F7CD9786" + } + ] +} diff --git a/tests/src/androidInstrumentedTest/assets/musig2/sig_agg_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/sig_agg_vectors.json new file mode 100644 index 0000000..04a7bc6 --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/sig_agg_vectors.json @@ -0,0 +1,151 @@ +{ + "pubkeys": [ + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "02D2DC6F5DF7C56ACF38C7FA0AE7A759AE30E19B37359DFDE015872324C7EF6E05", + "03C7FB101D97FF930ACD0C6760852EF64E69083DE0B06AC6335724754BB4B0522C", + "02352433B21E7E05D3B452B81CAE566E06D2E003ECE16D1074AABA4289E0E3D581" + ], + "pnonces": [ + "036E5EE6E28824029FEA3E8A9DDD2C8483F5AF98F7177C3AF3CB6F47CAF8D94AE902DBA67E4A1F3680826172DA15AFB1A8CA85C7C5CC88900905C8DC8C328511B53E", + "03E4F798DA48A76EEC1C9CC5AB7A880FFBA201A5F064E627EC9CB0031D1D58FC5103E06180315C5A522B7EC7C08B69DCD721C313C940819296D0A7AB8E8795AC1F00", + "02C0068FD25523A31578B8077F24F78F5BD5F2422AFF47C1FADA0F36B3CEB6C7D202098A55D1736AA5FCC21CF0729CCE852575C06C081125144763C2C4C4A05C09B6", + "031F5C87DCFBFCF330DEE4311D85E8F1DEA01D87A6F1C14CDFC7E4F1D8C441CFA40277BF176E9F747C34F81B0D9F072B1B404A86F402C2D86CF9EA9E9C69876EA3B9", + "023F7042046E0397822C4144A17F8B63D78748696A46C3B9F0A901D296EC3406C302022B0B464292CF9751D699F10980AC764E6F671EFCA15069BBE62B0D1C62522A", + "02D97DDA5988461DF58C5897444F116A7C74E5711BF77A9446E27806563F3B6C47020CBAD9C363A7737F99FA06B6BE093CEAFF5397316C5AC46915C43767AE867C00" + ], + "tweaks": [ + "B511DA492182A91B0FFB9A98020D55F260AE86D7ECBD0399C7383D59A5F2AF7C", + "A815FE049EE3C5AAB66310477FBC8BCCCAC2F3395F59F921C364ACD78A2F48DC", + "75448A87274B056468B977BE06EB1E9F657577B7320B0A3376EA51FD420D18A8" + ], + "psigs": [ + "B15D2CD3C3D22B04DAE438CE653F6B4ECF042F42CFDED7C41B64AAF9B4AF53FB", + "6193D6AC61B354E9105BBDC8937A3454A6D705B6D57322A5A472A02CE99FCB64", + "9A87D3B79EC67228CB97878B76049B15DBD05B8158D17B5B9114D3C226887505", + "66F82EA90923689B855D36C6B7E032FB9970301481B99E01CDB4D6AC7C347A15", + "4F5AEE41510848A6447DCD1BBC78457EF69024944C87F40250D3EF2C25D33EFE", + "DDEF427BBB847CC027BEFF4EDB01038148917832253EBC355FC33F4A8E2FCCE4", + "97B890A26C981DA8102D3BC294159D171D72810FDF7C6A691DEF02F0F7AF3FDC", + "53FA9E08BA5243CBCB0D797C5EE83BC6728E539EB76C2D0BF0F971EE4E909971", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" + ], + "msg": "599C67EA410D005B9DA90817CF03ED3B1C868E4DA4EDF00A5880B0082C237869", + "valid_test_cases": [ + { + "aggnonce": "0341432722C5CD0268D829C702CF0D1CBCE57033EED201FD335191385227C3210C03D377F2D258B64AADC0E16F26462323D701D286046A2EA93365656AFD9875982B", + "nonce_indices": [ + 0, + 1 + ], + "key_indices": [ + 0, + 1 + ], + "tweak_indices": [], + "is_xonly": [], + "psig_indices": [ + 0, + 1 + ], + "expected": "041DA22223CE65C92C9A0D6C2CAC828AAF1EEE56304FEC371DDF91EBB2B9EF0912F1038025857FEDEB3FF696F8B99FA4BB2C5812F6095A2E0004EC99CE18DE1E" + }, + { + "aggnonce": "0224AFD36C902084058B51B5D36676BBA4DC97C775873768E58822F87FE437D792028CB15929099EEE2F5DAE404CD39357591BA32E9AF4E162B8D3E7CB5EFE31CB20", + "nonce_indices": [ + 0, + 2 + ], + "key_indices": [ + 0, + 2 + ], + "tweak_indices": [], + "is_xonly": [], + "psig_indices": [ + 2, + 3 + ], + "expected": "1069B67EC3D2F3C7C08291ACCB17A9C9B8F2819A52EB5DF8726E17E7D6B52E9F01800260A7E9DAC450F4BE522DE4CE12BA91AEAF2B4279219EF74BE1D286ADD9" + }, + { + "aggnonce": "0208C5C438C710F4F96A61E9FF3C37758814B8C3AE12BFEA0ED2C87FF6954FF186020B1816EA104B4FCA2D304D733E0E19CEAD51303FF6420BFD222335CAA402916D", + "nonce_indices": [ + 0, + 3 + ], + "key_indices": [ + 0, + 2 + ], + "tweak_indices": [ + 0 + ], + "is_xonly": [ + false + ], + "psig_indices": [ + 4, + 5 + ], + "expected": "5C558E1DCADE86DA0B2F02626A512E30A22CF5255CAEA7EE32C38E9A71A0E9148BA6C0E6EC7683B64220F0298696F1B878CD47B107B81F7188812D593971E0CC" + }, + { + "aggnonce": "02B5AD07AFCD99B6D92CB433FBD2A28FDEB98EAE2EB09B6014EF0F8197CD58403302E8616910F9293CF692C49F351DB86B25E352901F0E237BAFDA11F1C1CEF29FFD", + "nonce_indices": [ + 0, + 4 + ], + "key_indices": [ + 0, + 3 + ], + "tweak_indices": [ + 0, + 1, + 2 + ], + "is_xonly": [ + true, + false, + true + ], + "psig_indices": [ + 6, + 7 + ], + "expected": "839B08820B681DBA8DAF4CC7B104E8F2638F9388F8D7A555DC17B6E6971D7426CE07BF6AB01F1DB50E4E33719295F4094572B79868E440FB3DEFD3FAC1DB589E" + } + ], + "error_test_cases": [ + { + "aggnonce": "02B5AD07AFCD99B6D92CB433FBD2A28FDEB98EAE2EB09B6014EF0F8197CD58403302E8616910F9293CF692C49F351DB86B25E352901F0E237BAFDA11F1C1CEF29FFD", + "nonce_indices": [ + 0, + 4 + ], + "key_indices": [ + 0, + 3 + ], + "tweak_indices": [ + 0, + 1, + 2 + ], + "is_xonly": [ + true, + false, + true + ], + "psig_indices": [ + 7, + 8 + ], + "error": { + "type": "invalid_contribution", + "signer": 1 + }, + "comment": "Partial signature is invalid because it exceeds group size" + } + ] +} diff --git a/tests/src/androidInstrumentedTest/assets/musig2/sign_verify_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/sign_verify_vectors.json new file mode 100644 index 0000000..b467640 --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/sign_verify_vectors.json @@ -0,0 +1,212 @@ +{ + "sk": "7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671", + "pubkeys": [ + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA661", + "020000000000000000000000000000000000000000000000000000000000000007" + ], + "secnonces": [ + "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F703935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9" + ], + "pnonces": [ + "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "032DE2662628C90B03F5E720284EB52FF7D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1CA6BEB2090C93D930321071AD40B2F44E599046", + "0237C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0387BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "0200000000000000000000000000000000000000000000000000000000000000090287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480" + ], + "aggnonces": [ + "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "048465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9", + "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61020000000000000000000000000000000000000000000000000000000000000009", + "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD6102FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30" + ], + "msgs": [ + "F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF", + "", + "2626262626262626262626262626262626262626262626262626262626262626262626262626" + ], + "valid_test_cases": [ + { + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 0, + "expected": "012ABBCB52B3016AC03AD82395A1A415C48B93DEF78718E62A7A90052FE224FB" + }, + { + "key_indices": [1, 0, 2], + "nonce_indices": [1, 0, 2], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 1, + "expected": "9FF2F7AAA856150CC8819254218D3ADEEB0535269051897724F9DB3789513A52" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 2, + "expected": "FA23C359F6FAC4E7796BB93BC9F0532A95468C539BA20FF86D7C76ED92227900" + }, + { + "key_indices": [0, 1], + "nonce_indices": [0, 3], + "aggnonce_index": 1, + "msg_index": 0, + "signer_index": 0, + "expected": "AE386064B26105404798F75DE2EB9AF5EDA5387B064B83D049CB7C5E08879531", + "comment": "Both halves of aggregate nonce correspond to point at infinity" + }, + { + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "aggnonce_index": 0, + "msg_index": 1, + "signer_index": 0, + "expected": "D7D63FFD644CCDA4E62BC2BC0B1D02DD32A1DC3030E155195810231D1037D82D", + "comment": "Empty message" + }, + { + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "aggnonce_index": 0, + "msg_index": 2, + "signer_index": 0, + "expected": "E184351828DA5094A97C79CABDAAA0BFB87608C32E8829A4DF5340A6F243B78C", + "comment": "38-byte message" + } + ], + "sign_error_test_cases": [ + { + "key_indices": [1, 2], + "aggnonce_index": 0, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "value", + "message": "The signer's pubkey must be included in the list of pubkeys." + }, + "comment": "The signers pubkey is not in the list of pubkeys. This test case is optional: it can be skipped by implementations that do not check that the signer's pubkey is included in the list of pubkeys." + }, + { + "key_indices": [1, 0, 3], + "aggnonce_index": 0, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": 2, + "contrib": "pubkey" + }, + "comment": "Signer 2 provided an invalid public key" + }, + { + "key_indices": [1, 2, 0], + "aggnonce_index": 2, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggnonce" + }, + "comment": "Aggregate nonce is invalid due wrong tag, 0x04, in the first half" + }, + { + "key_indices": [1, 2, 0], + "aggnonce_index": 3, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggnonce" + }, + "comment": "Aggregate nonce is invalid because the second half does not correspond to an X coordinate" + }, + { + "key_indices": [1, 2, 0], + "aggnonce_index": 4, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggnonce" + }, + "comment": "Aggregate nonce is invalid because second half exceeds field size" + }, + { + "key_indices": [0, 1, 2], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 0, + "secnonce_index": 1, + "error": { + "type": "value", + "message": "first secnonce value is out of range." + }, + "comment": "Secnonce is invalid which may indicate nonce reuse" + } + ], + "verify_fail_test_cases": [ + { + "sig": "97AC833ADCB1AFA42EBF9E0725616F3C9A0D5B614F6FE283CEAAA37A8FFAF406", + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 0, + "comment": "Wrong signature (which is equal to the negation of valid signature)" + }, + { + "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B", + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 1, + "comment": "Wrong signer" + }, + { + "sig": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 0, + "comment": "Signature exceeds group size" + } + ], + "verify_error_test_cases": [ + { + "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B", + "key_indices": [0, 1, 2], + "nonce_indices": [4, 1, 2], + "msg_index": 0, + "signer_index": 0, + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubnonce" + }, + "comment": "Invalid pubnonce" + }, + { + "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B", + "key_indices": [3, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 0, + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubkey" + }, + "comment": "Invalid pubkey" + } + ] +} diff --git a/tests/src/androidInstrumentedTest/assets/musig2/tweak_vectors.json b/tests/src/androidInstrumentedTest/assets/musig2/tweak_vectors.json new file mode 100644 index 0000000..d0a7cfe --- /dev/null +++ b/tests/src/androidInstrumentedTest/assets/musig2/tweak_vectors.json @@ -0,0 +1,84 @@ +{ + "sk": "7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671", + "pubkeys": [ + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659" + ], + "secnonce": "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F703935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "pnonces": [ + "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "032DE2662628C90B03F5E720284EB52FF7D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1CA6BEB2090C93D930321071AD40B2F44E599046" + ], + "aggnonce": "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9", + "tweaks": [ + "E8F791FF9225A2AF0102AFFF4A9A723D9612A682A25EBE79802B263CDFCD83BB", + "AE2EA797CC0FE72AC5B97B97F3C6957D7E4199A167A58EB08BCAFFDA70AC0455", + "F52ECBC565B3D8BEA2DFD5B75A4F457E54369809322E4120831626F290FA87E0", + "1969AD73CC177FA0B4FCED6DF1F7BF9907E665FDE9BA196A74FED0A3CF5AEF9D", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" + ], + "msg": "F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF", + "valid_test_cases": [ + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0], + "is_xonly": [true], + "signer_index": 2, + "expected": "E28A5C66E61E178C2BA19DB77B6CF9F7E2F0F56C17918CD13135E60CC848FE91", + "comment": "A single x-only tweak" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0], + "is_xonly": [false], + "signer_index": 2, + "expected": "38B0767798252F21BF5702C48028B095428320F73A4B14DB1E25DE58543D2D2D", + "comment": "A single plain tweak" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0, 1], + "is_xonly": [false, true], + "signer_index": 2, + "expected": "408A0A21C4A0F5DACAF9646AD6EB6FECD7F7A11F03ED1F48DFFF2185BC2C2408", + "comment": "A plain tweak followed by an x-only tweak" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0, 1, 2, 3], + "is_xonly": [false, false, true, true], + "signer_index": 2, + "expected": "45ABD206E61E3DF2EC9E264A6FEC8292141A633C28586388235541F9ADE75435", + "comment": "Four tweaks: plain, plain, x-only, x-only." + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0, 1, 2, 3], + "is_xonly": [true, false, true, false], + "signer_index": 2, + "expected": "B255FDCAC27B40C7CE7848E2D3B7BF5EA0ED756DA81565AC804CCCA3E1D5D239", + "comment": "Four tweaks: x-only, plain, x-only, plain. If an implementation prohibits applying plain tweaks after x-only tweaks, it can skip this test vector or return an error." + } + ], + "error_test_cases": [ + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [4], + "is_xonly": [false], + "signer_index": 2, + "error": { + "type": "value", + "message": "The tweak must be less than n." + }, + "comment": "Tweak is invalid because it exceeds group size" + } + ] +} diff --git a/tests/src/androidInstrumentedTest/kotlin/fr/acinq/secp256k1/TestHelpers.android.kt b/tests/src/androidInstrumentedTest/kotlin/fr/acinq/secp256k1/TestHelpers.android.kt new file mode 100644 index 0000000..7e7c1c3 --- /dev/null +++ b/tests/src/androidInstrumentedTest/kotlin/fr/acinq/secp256k1/TestHelpers.android.kt @@ -0,0 +1,16 @@ +package fr.acinq.secp256k1 + +import androidx.test.platform.app.InstrumentationRegistry +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement + +val context = InstrumentationRegistry.getInstrumentation().targetContext +val assetManager = context.assets + +actual fun readResourceAsJson(filename: String): JsonElement { + // Open the file from the assets folder + val inputStream = assetManager.open(filename) + val raw = inputStream.bufferedReader().use { it.readText() } + val format = Json { ignoreUnknownKeys = true } + return format.parseToJsonElement(raw) +} diff --git a/tests/src/androidUnitTest/kotlin/fr/acinq/secp256k1/TestHelpers.android.kt b/tests/src/androidUnitTest/kotlin/fr/acinq/secp256k1/TestHelpers.android.kt deleted file mode 100644 index cdc5453..0000000 --- a/tests/src/androidUnitTest/kotlin/fr/acinq/secp256k1/TestHelpers.android.kt +++ /dev/null @@ -1,5 +0,0 @@ -package fr.acinq.secp256k1 - -actual fun readEnvironmentVariable(name: String): String? { - return System.getenv(name) -} \ No newline at end of file diff --git a/tests/src/commonTest/kotlin/fr/acinq/secp256k1/Musig2Test.kt b/tests/src/commonTest/kotlin/fr/acinq/secp256k1/Musig2Test.kt index 380cfc6..42e577f 100644 --- a/tests/src/commonTest/kotlin/fr/acinq/secp256k1/Musig2Test.kt +++ b/tests/src/commonTest/kotlin/fr/acinq/secp256k1/Musig2Test.kt @@ -5,8 +5,8 @@ import kotlin.test.* class Musig2Test { @Test - fun `aggregate public keys`() { - val tests = TestHelpers.readResourceAsJson("musig2/key_agg_vectors.json") + fun aggregatePublicKeys() { + val tests = readResourceAsJson("musig2/key_agg_vectors.json") val pubkeys = tests.jsonObject["pubkeys"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } val tweaks = tests.jsonObject["tweaks"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } @@ -62,8 +62,8 @@ class Musig2Test { } @Test - fun `generate secret nonce`() { - val tests = TestHelpers.readResourceAsJson("musig2/nonce_gen_vectors.json") + fun generateSecretNonce() { + val tests = readResourceAsJson("musig2/nonce_gen_vectors.json") tests.jsonObject["test_cases"]!!.jsonArray.forEach { val randprime = Hex.decode(it.jsonObject["rand_"]!!.jsonPrimitive.content) val sk = it.jsonObject["sk"]?.jsonPrimitive?.contentOrNull?.let { Hex.decode(it) } @@ -91,7 +91,7 @@ class Musig2Test { } @Test - fun `generate secret nonce from counter`() { + fun generateSecretNonceFromCounter() { val sk = Hex.decode("EEC1CB7D1B7254C5CAB0D9C61AB02E643D464A59FE6C96A7EFE871F07C5AEF54") val nonce = Secp256k1.musigNonceGenCounter(0UL, sk, null, null, null) val secnonce = nonce.copyOfRange(0, Secp256k1.MUSIG2_SECRET_NONCE_SIZE) @@ -101,8 +101,8 @@ class Musig2Test { } @Test - fun `aggregate nonces`() { - val tests = TestHelpers.readResourceAsJson("musig2/nonce_agg_vectors.json") + fun aggregateNonces() { + val tests = readResourceAsJson("musig2/nonce_agg_vectors.json") val nonces = tests.jsonObject["pnonces"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } tests.jsonObject["valid_test_cases"]!!.jsonArray.forEach { val nonceIndices = it.jsonObject["pnonce_indices"]!!.jsonArray.map { it.jsonPrimitive.int } @@ -121,7 +121,7 @@ class Musig2Test { @Test fun sign() { - val tests = TestHelpers.readResourceAsJson("musig2/sign_verify_vectors.json") + val tests = readResourceAsJson("musig2/sign_verify_vectors.json") val sk = Hex.decode(tests.jsonObject["sk"]!!.jsonPrimitive.content) val pubkeys = tests.jsonObject["pubkeys"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } val secnonces = tests.jsonObject["secnonces"]!!.jsonArray.map { deserializeSecretNonce(it.jsonPrimitive.content) } @@ -170,8 +170,8 @@ class Musig2Test { } @Test - fun `aggregate signatures`() { - val tests = TestHelpers.readResourceAsJson("musig2/sig_agg_vectors.json") + fun aggregateSignatures() { + val tests = readResourceAsJson("musig2/sig_agg_vectors.json") val pubkeys = tests.jsonObject["pubkeys"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } val pnonces = tests.jsonObject["pnonces"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } val tweaks = tests.jsonObject["tweaks"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } @@ -231,8 +231,8 @@ class Musig2Test { } @Test - fun `tweak tests`() { - val tests = TestHelpers.readResourceAsJson("musig2/tweak_vectors.json") + fun tweakTests() { + val tests = readResourceAsJson("musig2/tweak_vectors.json") val sk = Hex.decode(tests.jsonObject["sk"]!!.jsonPrimitive.content) val pubkeys = tests.jsonObject["pubkeys"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } val pnonces = tests.jsonObject["pnonces"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) } diff --git a/tests/src/commonTest/kotlin/fr/acinq/secp256k1/TestHelpers.kt b/tests/src/commonTest/kotlin/fr/acinq/secp256k1/TestHelpers.kt index 6cbfb9e..a451461 100644 --- a/tests/src/commonTest/kotlin/fr/acinq/secp256k1/TestHelpers.kt +++ b/tests/src/commonTest/kotlin/fr/acinq/secp256k1/TestHelpers.kt @@ -3,24 +3,15 @@ package fr.acinq.secp256k1 import kotlinx.io.buffered import kotlinx.io.files.Path import kotlinx.io.files.SystemFileSystem -import kotlinx.io.readByteArray import kotlinx.io.readString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement -object TestHelpers { - val resourcesPath = Path(readEnvironmentVariable("TEST_RESOURCES_PATH")?: "src/commonTest/resources") +expect fun readResourceAsJson(filename: String): JsonElement - fun readResourceAsJson(filename: String): JsonElement { - val raw = SystemFileSystem.source(Path(resourcesPath, filename)).buffered().readString() - val format = Json { ignoreUnknownKeys = true } - return format.parseToJsonElement(raw) - } - - - fun readResourceAsByteArray(filename: String): ByteArray { - return SystemFileSystem.source(Path(resourcesPath, filename)).buffered().readByteArray() - } +fun readResourceAsJsonDefault(filename: String): JsonElement { + val resourcesPath = "src/commonTest/resources" + val raw = SystemFileSystem.source(Path(resourcesPath, filename)).buffered().readString() + val format = Json { ignoreUnknownKeys = true } + return format.parseToJsonElement(raw) } - -expect fun readEnvironmentVariable(name: String): String? diff --git a/tests/src/jvmTest/kotlin/fr/acinq/secp256k1/TestHelpers.jvm.kt b/tests/src/jvmTest/kotlin/fr/acinq/secp256k1/TestHelpers.jvm.kt index cdc5453..c558609 100644 --- a/tests/src/jvmTest/kotlin/fr/acinq/secp256k1/TestHelpers.jvm.kt +++ b/tests/src/jvmTest/kotlin/fr/acinq/secp256k1/TestHelpers.jvm.kt @@ -1,5 +1,5 @@ package fr.acinq.secp256k1 -actual fun readEnvironmentVariable(name: String): String? { - return System.getenv(name) -} \ No newline at end of file +import kotlinx.serialization.json.JsonElement + +actual fun readResourceAsJson(filename: String): JsonElement = readResourceAsJsonDefault(filename) \ No newline at end of file diff --git a/tests/src/nativeTest/kotlin/fr/acinq/secp256k1/TestHelpers.native.kt b/tests/src/nativeTest/kotlin/fr/acinq/secp256k1/TestHelpers.native.kt index 9ed544a..c558609 100644 --- a/tests/src/nativeTest/kotlin/fr/acinq/secp256k1/TestHelpers.native.kt +++ b/tests/src/nativeTest/kotlin/fr/acinq/secp256k1/TestHelpers.native.kt @@ -1,9 +1,5 @@ package fr.acinq.secp256k1 -import platform.posix.* -import kotlinx.cinterop.* +import kotlinx.serialization.json.JsonElement -@OptIn(ExperimentalForeignApi::class) -actual fun readEnvironmentVariable(name: String): String? { - return getenv(name)?.toKString() -} \ No newline at end of file +actual fun readResourceAsJson(filename: String): JsonElement = readResourceAsJsonDefault(filename) \ No newline at end of file