Android implementation
This commit is contained in:
parent
08b6d16836
commit
ff37b86ff3
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@ build/
|
||||
.gradle
|
||||
local.properties
|
||||
.gradletasknamecache
|
||||
.cxx
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
@ -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<com.android.build.gradle.tasks.factory.AndroidUnitTest>().all {
|
||||
enabled = false
|
||||
}
|
||||
}
|
@ -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
|
48
native/build-android.sh
Executable file
48
native/build-android.sh
Executable file
@ -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
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
3
src/androidMain/AndroidManifest.xml
Normal file
3
src/androidMain/AndroidManifest.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="fr.acinq.secp256k1">
|
||||
</manifest>
|
14
src/androidMain/CMakeLists.txt
Normal file
14
src/androidMain/CMakeLists.txt
Normal file
@ -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
|
||||
)
|
15
src/androidMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt
Normal file
15
src/androidMain/kotlin/fr/acinq/secp256k1/Secp256k1Loader.kt
Normal file
@ -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")
|
||||
}
|
||||
|
||||
}
|
4
src/androidTest/java/fr/acinq/secp256k1/Placeholder.kt
Normal file
4
src/androidTest/java/fr/acinq/secp256k1/Placeholder.kt
Normal file
@ -0,0 +1,4 @@
|
||||
package fr.acinq.secp256k1
|
||||
|
||||
|
||||
class Placeholder {}
|
@ -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 {
|
||||
|
@ -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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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<ByteArray>
|
||||
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()
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user