From ff37b86ff3c741491a2ad0cac7ef0b94020b2676 Mon Sep 17 00:00:00 2001 From: Salomon BRYS Date: Fri, 26 Jun 2020 20:50:32 +0200 Subject: [PATCH] Android implementation --- .gitignore | 1 + build.gradle.kts | 97 ++++++++++++-- gradle.properties | 17 ++- native/build-android.sh | 48 +++++++ native/build.sh | 12 +- settings.gradle.kts | 8 +- src/androidMain/AndroidManifest.xml | 3 + src/androidMain/CMakeLists.txt | 14 ++ .../fr/acinq/secp256k1/Secp256k1Loader.kt | 15 +++ .../java/fr/acinq/secp256k1/Placeholder.kt | 4 + .../kotlin/fr/acinq/secp256k1/Secp256k1.kt | 5 +- .../kotlin/org/bitcoin/NativeSecp256k1.kt | 122 ++++++++++++++---- .../kotlin/org/bitcoin/NativeSecp256k1Util.kt | 0 .../kotlin/org/bitcoin/Secp256k1Context.kt | 22 +--- .../fr/acinq/secp256k1/Secp256k1Loader.kt | 7 +- 15 files changed, 303 insertions(+), 72 deletions(-) create mode 100755 native/build-android.sh create mode 100644 src/androidMain/AndroidManifest.xml create mode 100644 src/androidMain/CMakeLists.txt create mode 100644 src/androidMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt create mode 100644 src/androidTest/java/fr/acinq/secp256k1/Placeholder.kt rename src/{jvmMain => jvmAndAndroidMain}/kotlin/fr/acinq/secp256k1/Secp256k1.kt (97%) rename src/{jvmMain => jvmAndAndroidMain}/kotlin/org/bitcoin/NativeSecp256k1.kt (85%) rename src/{jvmMain => jvmAndAndroidMain}/kotlin/org/bitcoin/NativeSecp256k1Util.kt (100%) rename src/{jvmMain => jvmAndAndroidMain}/kotlin/org/bitcoin/Secp256k1Context.kt (64%) diff --git a/.gitignore b/.gitignore index 10b2c3f..aa419fa 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ build/ .gradle local.properties .gradletasknamecache +.cxx # OS .DS_Store diff --git a/build.gradle.kts b/build.gradle.kts index 4d5d657..30114a0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,13 @@ plugins { kotlin("multiplatform") version "1.4-M2-mt" + id("com.android.library") version "4.0.0" } group = "fr.acinq.phoenix" version = "1.0-1.4-M2" repositories { jcenter() + google() maven(url = "https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlin-eap") } @@ -27,6 +29,13 @@ kotlin { } } + val jvmAndAndroidMain by sourceSets.creating { + dependsOn(commonMain) + dependencies { + implementation(kotlin("stdlib-jdk8")) + } + } + jvm { compilations.all { kotlinOptions.jvmTarget = "1.8" @@ -35,14 +44,24 @@ kotlin { dependsOn("copyJni") from(buildDir.resolve("jniResources")) } - compilations["main"].dependencies { - implementation(kotlin("stdlib-jdk8")) - } + compilations["main"].defaultSourceSet.dependsOn(jvmAndAndroidMain) compilations["test"].dependencies { implementation(kotlin("test-junit")) } } + android { + compilations.all { + kotlinOptions.jvmTarget = "1.8" + } + sourceSets["androidMain"].dependsOn(jvmAndAndroidMain) + sourceSets["androidTest"].dependencies { + implementation(kotlin("test-junit")) + implementation("androidx.test.ext:junit:1.1.1") + implementation("androidx.test.espresso:espresso-core:3.2.0") + } + } + fun org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget.secp256k1CInterop() { compilations["main"].cinterops { val libsecp256k1 by creating { @@ -75,6 +94,26 @@ kotlin { } +android { + defaultConfig { + compileSdkVersion(30) + minSdkVersion(21) + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake {} + } + } + + externalNativeBuild { + cmake { + setPath("src/androidMain/CMakeLists.txt") + } + } + ndkVersion = "21.3.6528147" + + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") +} + val buildSecp256k1 by tasks.creating { group = "build" } fun creatingBuildSecp256k1(target: String, cross: String? = null, env: String = "", configuration: Task.() -> Unit = {}) = tasks.creating(Exec::class) { group = "build" @@ -95,6 +134,14 @@ val buildSecp256k1Darwin by creatingBuildSecp256k1("darwin") val buildSecp256k1Linux by creatingBuildSecp256k1("linux", cross = if (currentOs.isMacOsX) "linux-x64" else null) val buildSecp256k1Mingw by creatingBuildSecp256k1("mingw", cross = "windows-x64", env = "CONF_OPTS=--host=x86_64-w64-mingw32") +val copyJni by tasks.creating(Sync::class) { + dependsOn(buildSecp256k1) + from(projectDir.resolve("native/build/linux/libsecp256k1-jni.so")) { rename { "libsecp256k1-jni-linux-x86_64.so" } } + from(projectDir.resolve("native/build/darwin/libsecp256k1-jni.dylib")) { rename { "libsecp256k1-jni-darwin-x86_64.dylib" } } + from(projectDir.resolve("native/build/mingw/secp256k1-jni.dll")) { rename { "secp256k1-jni-mingw-x86_64.dll" } } + into(buildDir.resolve("jniResources/fr/acinq/secp256k1/native")) +} + val buildSecp256k1Ios by tasks.creating(Exec::class) { group = "build" buildSecp256k1.dependsOn(this) @@ -106,10 +153,42 @@ val buildSecp256k1Ios by tasks.creating(Exec::class) { commandLine("./build-ios.sh") } -val copyJni by tasks.creating(Sync::class) { - dependsOn(buildSecp256k1) - from(projectDir.resolve("native/build/linux/libsecp256k1-jni.so")) { rename { "libsecp256k1-jni-linux-x86_64.so" } } - from(projectDir.resolve("native/build/darwin/libsecp256k1-jni.dylib")) { rename { "libsecp256k1-jni-darwin-x86_64.dylib" } } - from(projectDir.resolve("native/build/mingw/secp256k1-jni.dll")) { rename { "secp256k1-jni-mingw-x86_64.dll" } } - into(buildDir.resolve("jniResources/fr/acinq/secp256k1/native")) +val buildSecp256k1Android by tasks.creating { group = "build" } +fun creatingBuildSecp256k1Android(arch: String) = tasks.creating(Exec::class) { + group = "build" + buildSecp256k1Android.dependsOn(this) + + inputs.files(projectDir.resolve("native/build-android.sh")) + outputs.dir(projectDir.resolve("native/build/android/$arch")) + + workingDir = projectDir.resolve("native") + + val toolchain = when { + currentOs.isMacOsX -> "darwin-x86_64" + else -> error("Cannot build for Android on this OS") + } + environment("TOOLCHAIN", toolchain) + environment("ARCH", arch) + environment("ANDROID_NDK", android.ndkDirectory) + commandLine("./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") + +afterEvaluate { + configure(listOf("Debug", "Release").map { tasks["externalNativeBuild$it"] }) { + dependsOn(buildSecp256k1Android) + } +} + +tasks["clean"].doLast { + delete(projectDir.resolve("native/build")) +} + +afterEvaluate { + tasks.withType().all { + enabled = false + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 854f123..1cf1076 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,16 @@ # gradle -org.gradle.jvmargs=-Xmx1536m -org.gradle.parallel=true +org.gradle.jvmargs = -Xmx1536m +org.gradle.parallel = true # kotlin -kotlin.code.style=official +kotlin.code.style = official kotlin.incremental.multiplatform = true -kotlin.parallel.tasks.in.project=true -#kotlin.mpp.enableGranularSourceSetsMetadata=true -kotlin.native.enableDependencyPropagation=false +kotlin.parallel.tasks.in.project = true +#kotlin.mpp.enableGranularSourceSetsMetadata = true +kotlin.native.enableDependencyPropagation = false # https://github.com/gradle/gradle/issues/11412 -systemProp.org.gradle.internal.publish.checksums.insecure=true +systemProp.org.gradle.internal.publish.checksums.insecure = true + +# Android +android.useAndroidX = true \ No newline at end of file diff --git a/native/build-android.sh b/native/build-android.sh new file mode 100755 index 0000000..d57acdc --- /dev/null +++ b/native/build-android.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -e + +ANDROID_NDK=/Users/salomonbrys/Library/Android/sdk/ndk/21.3.6528147 +TOOLCHAIN=darwin-x86_64 + +[[ -z "$ANDROID_NDK" ]] && echo "Please set the ANDROID_NDK variable" && exit 1 +[[ -z "$ARCH" ]] && echo "Please set the ARCH variable" && exit 1 +[[ -z "$TOOLCHAIN" ]] && echo "Please set the TOOLCHAIN variable" && exit 1 + +if [ "$ARCH" == "x86_64" ]; then + SYS=x86_64 +elif [ "$ARCH" == "x86" ]; then + SYS=i686 +elif [ "$ARCH" == "arm64-v8a" ]; then + SYS=aarch64 +elif [ "$ARCH" == "armeabi-v7a" ]; then + SYS=armv7a +else + echo "Unsupported ARCH: $ARCH" + exit 1 +fi + +TARGET=$SYS-linux-android +TOOLTARGET=$TARGET +if [ "$SYS" == "armv7a" ]; then + TARGET=armv7a-linux-androideabi + TOOLTARGET=arm-linux-androideabi +fi + +export CC=$ANDROID_NDK/toolchains/llvm/prebuilt/$TOOLCHAIN/bin/${TARGET}21-clang +export LD=$ANDROID_NDK/toolchains/llvm/prebuilt/$TOOLCHAIN/bin/$TOOLTARGET-ld +export AR=$ANDROID_NDK/toolchains/llvm/prebuilt/$TOOLCHAIN/bin/$TOOLTARGET-ar +export AS=$ANDROID_NDK/toolchains/llvm/prebuilt/$TOOLCHAIN/bin/$TOOLTARGET-as +export RANLIB=$ANDROID_NDK/toolchains/llvm/prebuilt/$TOOLCHAIN/bin/$TOOLTARGET-ranlib +export STRIP=$ANDROID_NDK/toolchains/llvm/prebuilt/$TOOLCHAIN/bin/$TOOLTARGET-strip + +cd secp256k1 + +./autogen.sh +./configure CFLAGS=-fpic --host=$TARGET --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no +make clean +make + +cd .. + +mkdir -p build/android/$ARCH +cp -v secp256k1/.libs/libsecp256k1.a build/android/$ARCH diff --git a/native/build.sh b/native/build.sh index 072f22d..3f891c8 100755 --- a/native/build.sh +++ b/native/build.sh @@ -19,9 +19,9 @@ make cd .. mkdir -p build/$TARGET -cp -r secp256k1/.libs/libsecp256k1.a build/$TARGET/ +cp -v secp256k1/.libs/libsecp256k1.a build/$TARGET/ -GCC=gcc +CC=gcc JNI_HEADERS=$TARGET if [ "$TARGET" == "linux" ]; then @@ -31,11 +31,9 @@ elif [ "$TARGET" == "darwin" ]; then ADD_LIB=-lgmp elif [ "$TARGET" == "mingw" ]; then OUTFILE=secp256k1-jni.dll - GCC=/usr/src/mxe/usr/bin/x86_64-w64-mingw32.static-gcc + CC=/usr/src/mxe/usr/bin/x86_64-w64-mingw32.static-gcc JNI_HEADERS=linux - GCC_OPTS="-fpic" + CC_OPTS="-fpic" fi -echo $GCC -shared $GCC_OPTS -o build/$TARGET/$OUTFILE jni/src/org_bitcoin_NativeSecp256k1.c jni/src/org_bitcoin_Secp256k1Context.c -Ijni/headers/ -Ijni/headers/$JNI_HEADERS/ -Isecp256k1/ -lsecp256k1 -Lbuild/$TARGET/ $ADD_LIB - -$GCC -shared $GCC_OPTS -o build/$TARGET/$OUTFILE jni/src/org_bitcoin_NativeSecp256k1.c jni/src/org_bitcoin_Secp256k1Context.c -Ijni/headers/ -Ijni/headers/$JNI_HEADERS/ -Isecp256k1/ -lsecp256k1 -Lbuild/$TARGET/ $ADD_LIB +$CC -shared $CC_OPTS -o build/$TARGET/$OUTFILE jni/src/org_bitcoin_NativeSecp256k1.c jni/src/org_bitcoin_Secp256k1Context.c -Ijni/headers/ -Ijni/headers/$JNI_HEADERS/ -Isecp256k1/ -lsecp256k1 -Lbuild/$TARGET/ $ADD_LIB diff --git a/settings.gradle.kts b/settings.gradle.kts index 0baa797..70ac468 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,7 @@ pluginManagement { repositories { mavenCentral() + google() gradlePluginPortal() maven { url = uri("https://dl.bintray.com/kotlin/kotlin-eap") @@ -8,7 +9,12 @@ pluginManagement { maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://plugins.gradle.org/m2/") } - + + resolutionStrategy { + eachPlugin { + if (requested.id.id == "com.android.library") useModule("com.android.tools.build:gradle:${requested.version}") + } + } } rootProject.name = "secp256k1-kmp" diff --git a/src/androidMain/AndroidManifest.xml b/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..2696859 --- /dev/null +++ b/src/androidMain/AndroidManifest.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/androidMain/CMakeLists.txt b/src/androidMain/CMakeLists.txt new file mode 100644 index 0000000..a2063a8 --- /dev/null +++ b/src/androidMain/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.10.0) + +add_library( secp256k1-jni SHARED + ${CMAKE_CURRENT_LIST_DIR}/../../native/jni/src/org_bitcoin_NativeSecp256k1.c + ${CMAKE_CURRENT_LIST_DIR}/../../native/jni/src/org_bitcoin_Secp256k1Context.c +) + +target_include_directories( secp256k1-jni + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/../../native/secp256k1 +) + +target_link_libraries( secp256k1-jni + ${CMAKE_CURRENT_LIST_DIR}/../../native/build/android/${ANDROID_ABI}/libsecp256k1.a +) diff --git a/src/androidMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt b/src/androidMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt new file mode 100644 index 0000000..75df1eb --- /dev/null +++ b/src/androidMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt @@ -0,0 +1,15 @@ +package fr.acinq.secp256k1 + +import java.io.* +import java.util.* + +internal actual object Secp256k1Loader { + + @JvmStatic + @Synchronized + @Throws(Exception::class) + actual fun initialize() { + System.loadLibrary("secp256k1-jni") + } + +} diff --git a/src/androidTest/java/fr/acinq/secp256k1/Placeholder.kt b/src/androidTest/java/fr/acinq/secp256k1/Placeholder.kt new file mode 100644 index 0000000..ca388d2 --- /dev/null +++ b/src/androidTest/java/fr/acinq/secp256k1/Placeholder.kt @@ -0,0 +1,4 @@ +package fr.acinq.secp256k1 + + +class Placeholder {} diff --git a/src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt b/src/jvmAndAndroidMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt similarity index 97% rename from src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt rename to src/jvmAndAndroidMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt index 034649d..39ab393 100644 --- a/src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt +++ b/src/jvmAndAndroidMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt @@ -17,7 +17,10 @@ package fr.acinq.secp256k1 import org.bitcoin.NativeSecp256k1 -import java.math.BigInteger + +internal expect object Secp256k1Loader { + fun initialize() +} public actual object Secp256k1 { diff --git a/src/jvmMain/kotlin/org/bitcoin/NativeSecp256k1.kt b/src/jvmAndAndroidMain/kotlin/org/bitcoin/NativeSecp256k1.kt similarity index 85% rename from src/jvmMain/kotlin/org/bitcoin/NativeSecp256k1.kt rename to src/jvmAndAndroidMain/kotlin/org/bitcoin/NativeSecp256k1.kt index ac74318..b1be0f0 100644 --- a/src/jvmMain/kotlin/org/bitcoin/NativeSecp256k1.kt +++ b/src/jvmAndAndroidMain/kotlin/org/bitcoin/NativeSecp256k1.kt @@ -78,7 +78,12 @@ public object NativeSecp256k1 { val byteBuff = pack(data, signature, pub) r.lock() return try { - secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.size, pub.size) == 1 + secp256k1_ecdsa_verify( + byteBuff, + Secp256k1Context.getContext(), + signature.size, + pub.size + ) == 1 } finally { r.unlock() } @@ -100,14 +105,21 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()) + secp256k1_ecdsa_sign( + byteBuff, + Secp256k1Context.getContext() + ) } finally { r.unlock() } val sigArr = retByteArray[0] val sigLen = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt() - NativeSecp256k1Util.assertEquals(sigArr.size, sigLen, "Got bad signature length.") + NativeSecp256k1Util.assertEquals( + sigArr.size, + sigLen, + "Got bad signature length." + ) return if (retVal == 0) ByteArray(0) else sigArr } @@ -130,14 +142,21 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_ecdsa_sign_compact(byteBuff, Secp256k1Context.getContext()) + secp256k1_ecdsa_sign_compact( + byteBuff, + Secp256k1Context.getContext() + ) } finally { r.unlock() } val sigArr = retByteArray[0] val sigLen = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt() - NativeSecp256k1Util.assertEquals(sigArr.size, sigLen, "Got bad signature length.") + NativeSecp256k1Util.assertEquals( + sigArr.size, + sigLen, + "Got bad signature length." + ) return if (retVal == 0) ByteArray(0) else sigArr } @@ -153,7 +172,10 @@ public object NativeSecp256k1 { val byteBuff = pack(seckey) r.lock() return try { - secp256k1_ec_seckey_verify(byteBuff, Secp256k1Context.getContext()) == 1 + secp256k1_ec_seckey_verify( + byteBuff, + Secp256k1Context.getContext() + ) == 1 } finally { r.unlock() } @@ -175,7 +197,10 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()) + secp256k1_ec_pubkey_create( + byteBuff, + Secp256k1Context.getContext() + ) } finally { r.unlock() } @@ -199,12 +224,16 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_ec_pubkey_parse(byteBuff, Secp256k1Context.getContext(), pubkey.size) + secp256k1_ec_pubkey_parse( + byteBuff, + Secp256k1Context.getContext(), + pubkey.size + ) } finally { r.unlock() } val pubArr = retByteArray[0] - val pubLen = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() + BigInteger(byteArrayOf(retByteArray[1][0])).toInt() val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt() NativeSecp256k1Util.assertEquals(pubArr.size, 65, "Got bad pubkey length.") return if (retVal == 0) ByteArray(0) else pubArr @@ -233,14 +262,21 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_privkey_negate(byteBuff, Secp256k1Context.getContext()) + secp256k1_privkey_negate( + byteBuff, + Secp256k1Context.getContext() + ) } finally { r.unlock() } val privArr = retByteArray[0] val privLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt() - NativeSecp256k1Util.assertEquals(privArr.size, privLen, "Got bad privkey length.") + NativeSecp256k1Util.assertEquals( + privArr.size, + privLen, + "Got bad privkey length." + ) NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.") return privArr } @@ -257,18 +293,25 @@ public object NativeSecp256k1 { @Throws(AssertFailException::class) public fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray { require(privkey.size == 32) - val byteBuff = pack(privkey, tweak!!) + val byteBuff = pack(privkey, tweak) val retByteArray: Array r.lock() retByteArray = try { - secp256k1_privkey_tweak_mul(byteBuff, Secp256k1Context.getContext()) + secp256k1_privkey_tweak_mul( + byteBuff, + Secp256k1Context.getContext() + ) } finally { r.unlock() } val privArr = retByteArray[0] val privLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt() - NativeSecp256k1Util.assertEquals(privArr.size, privLen, "Got bad privkey length.") + NativeSecp256k1Util.assertEquals( + privArr.size, + privLen, + "Got bad privkey length." + ) NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.") return privArr } @@ -285,11 +328,14 @@ public object NativeSecp256k1 { @Throws(AssertFailException::class) public fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray { require(privkey.size == 32) - val byteBuff = pack(privkey, tweak!!) + val byteBuff = pack(privkey, tweak) val retByteArray: Array r.lock() retByteArray = try { - secp256k1_privkey_tweak_add(byteBuff, Secp256k1Context.getContext()) + secp256k1_privkey_tweak_add( + byteBuff, + Secp256k1Context.getContext() + ) } finally { r.unlock() } @@ -309,7 +355,11 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_pubkey_negate(byteBuff, Secp256k1Context.getContext(), pubkey.size) + secp256k1_pubkey_negate( + byteBuff, + Secp256k1Context.getContext(), + pubkey.size + ) } finally { r.unlock() } @@ -337,7 +387,11 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_pubkey_tweak_add(byteBuff, Secp256k1Context.getContext(), pubkey.size) + secp256k1_pubkey_tweak_add( + byteBuff, + Secp256k1Context.getContext(), + pubkey.size + ) } finally { r.unlock() } @@ -361,11 +415,15 @@ public object NativeSecp256k1 { @Throws(AssertFailException::class) public fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray { require(pubkey.size == 33 || pubkey.size == 65) - val byteBuff = pack(pubkey, tweak!!) + val byteBuff = pack(pubkey, tweak) val retByteArray: Array r.lock() retByteArray = try { - secp256k1_pubkey_tweak_mul(byteBuff, Secp256k1Context.getContext(), pubkey.size) + secp256k1_pubkey_tweak_mul( + byteBuff, + Secp256k1Context.getContext(), + pubkey.size + ) } finally { r.unlock() } @@ -386,7 +444,12 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_ec_pubkey_add(byteBuff, Secp256k1Context.getContext(), pubkey1.size, pubkey2.size) + secp256k1_ec_pubkey_add( + byteBuff, + Secp256k1Context.getContext(), + pubkey1.size, + pubkey2.size + ) } finally { r.unlock() } @@ -414,7 +477,11 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.size) + secp256k1_ecdh( + byteBuff, + Secp256k1Context.getContext(), + pubkey.size + ) } finally { r.unlock() } @@ -434,7 +501,11 @@ public object NativeSecp256k1 { val retByteArray: Array r.lock() retByteArray = try { - secp256k1_ecdsa_recover(byteBuff, Secp256k1Context.getContext(), recid) + secp256k1_ecdsa_recover( + byteBuff, + Secp256k1Context.getContext(), + recid + ) } finally { r.unlock() } @@ -460,7 +531,10 @@ public object NativeSecp256k1 { val byteBuff = pack(seed) w.lock() return try { - secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1 + secp256k1_context_randomize( + byteBuff, + Secp256k1Context.getContext() + ) == 1 } finally { w.unlock() } diff --git a/src/jvmMain/kotlin/org/bitcoin/NativeSecp256k1Util.kt b/src/jvmAndAndroidMain/kotlin/org/bitcoin/NativeSecp256k1Util.kt similarity index 100% rename from src/jvmMain/kotlin/org/bitcoin/NativeSecp256k1Util.kt rename to src/jvmAndAndroidMain/kotlin/org/bitcoin/NativeSecp256k1Util.kt diff --git a/src/jvmMain/kotlin/org/bitcoin/Secp256k1Context.kt b/src/jvmAndAndroidMain/kotlin/org/bitcoin/Secp256k1Context.kt similarity index 64% rename from src/jvmMain/kotlin/org/bitcoin/Secp256k1Context.kt rename to src/jvmAndAndroidMain/kotlin/org/bitcoin/Secp256k1Context.kt index 0a3c5e7..1d4731c 100644 --- a/src/jvmMain/kotlin/org/bitcoin/Secp256k1Context.kt +++ b/src/jvmAndAndroidMain/kotlin/org/bitcoin/Secp256k1Context.kt @@ -34,23 +34,7 @@ public object Secp256k1Context { @JvmStatic private external fun secp256k1_init_context(): Long init { //static initializer - var isEnabled = true - var contextRef: Long = -1 - try { - if ("The Android Project" == System.getProperty("java.vm.vendor")) { - System.loadLibrary("secp256k1") - } else { - initialize() - } - contextRef = secp256k1_init_context() - } catch (e: UnsatisfiedLinkError) { - println("Cannot load secp256k1 native library: $e") - isEnabled = false - } catch (e: Exception) { - println("Cannot load secp256k1 native library: $e") - isEnabled = false - } - this.isEnabled = isEnabled - this.context = contextRef + isEnabled = true + context = secp256k1_init_context() } -} \ No newline at end of file +} diff --git a/src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt b/src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt index 804663a..954ca19 100644 --- a/src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt +++ b/src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt @@ -26,7 +26,7 @@ import java.util.* * * @author leo */ -public object Secp256k1Loader { +internal actual object Secp256k1Loader { private var extracted = false /** @@ -38,13 +38,12 @@ public object Secp256k1Loader { @JvmStatic @Synchronized @Throws(Exception::class) - public fun initialize(): Boolean { + actual fun initialize() { // only cleanup before the first extract if (!extracted) { cleanup() } loadSecp256k1NativeLibrary() - return extracted } private val tempDir: File @@ -55,7 +54,7 @@ public object Secp256k1Loader { * on VM-Exit (bug #80) */ @JvmStatic - public fun cleanup() { + fun cleanup() { val tempFolder = tempDir.absolutePath val dir = File(tempFolder) val nativeLibFiles = dir.listFiles(object : FilenameFilter {