Compare commits
4 Commits
frost
...
snapshot/m
Author | SHA1 | Date | |
---|---|---|---|
|
951c843e27 | ||
|
3a983128c2 | ||
|
14da2e52d9 | ||
|
0c549c8bb7 |
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -86,7 +86,7 @@ jobs:
|
|||||||
- name: Check Linux
|
- name: Check Linux
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./gradlew linuxTest
|
run: ./gradlew linuxX64Test
|
||||||
- name: Check iOS
|
- name: Check iOS
|
||||||
if: matrix.os == 'macOS-latest'
|
if: matrix.os == 'macOS-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -103,7 +103,7 @@ jobs:
|
|||||||
- name: Publish Linux
|
- name: Publish Linux
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./gradlew publishLinuxPublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal
|
run: ./gradlew publishLinuxX64PublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal
|
||||||
- name: Publish Windows
|
- name: Publish Windows
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
|
4
.github/workflows/snapshot.yml
vendored
4
.github/workflows/snapshot.yml
vendored
@ -95,7 +95,7 @@ jobs:
|
|||||||
- name: Check Linux
|
- name: Check Linux
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./gradlew linuxTest
|
run: ./gradlew linuxX64Test
|
||||||
- name: Check iOS
|
- name: Check iOS
|
||||||
if: matrix.os == 'macOS-latest'
|
if: matrix.os == 'macOS-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -112,7 +112,7 @@ jobs:
|
|||||||
- name: Publish Linux
|
- name: Publish Linux
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./gradlew publishLinuxPublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
|
run: ./gradlew publishLinuxX64PublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
|
||||||
- name: Publish Windows
|
- name: Publish Windows
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -101,7 +101,7 @@ jobs:
|
|||||||
- name: Check Linux
|
- name: Check Linux
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./gradlew linuxTest
|
run: ./gradlew linuxX64Test
|
||||||
- name: Check iOS
|
- name: Check iOS
|
||||||
if: matrix.os == 'macOS-latest'
|
if: matrix.os == 'macOS-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
|||||||
[submodule "native/secp256k1"]
|
[submodule "native/secp256k1"]
|
||||||
path = native/secp256k1
|
path = native/secp256k1
|
||||||
url = https://github.com/bitcoin-core/secp256k1.git
|
url = https://github.com/jonasnick/secp256k1.git
|
||||||
|
@ -3,8 +3,8 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
|||||||
import org.jetbrains.dokka.Platform
|
import org.jetbrains.dokka.Platform
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform") version "1.8.21"
|
kotlin("multiplatform") version "1.9.21"
|
||||||
id("org.jetbrains.dokka") version "1.8.10"
|
id("org.jetbrains.dokka") version "1.9.10"
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,13 +16,13 @@ buildscript {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:7.3.1")
|
classpath("com.android.tools.build:gradle:7.3.1")
|
||||||
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.8.10")
|
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.9.10")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "fr.acinq.secp256k1"
|
group = "fr.acinq.secp256k1"
|
||||||
version = "0.12.1-SNAPSHOT"
|
version = "0.13.0-MUSIG2-SNAPSHOT"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
@ -52,20 +52,22 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val nativeMain by sourceSets.creating { dependsOn(commonMain) }
|
val nativeMain by sourceSets.creating
|
||||||
|
|
||||||
linuxX64("linux") {
|
linuxX64 {
|
||||||
secp256k1CInterop("host")
|
secp256k1CInterop("host")
|
||||||
compilations["main"].defaultSourceSet.dependsOn(nativeMain)
|
|
||||||
// https://youtrack.jetbrains.com/issue/KT-39396
|
|
||||||
compilations["main"].kotlinOptions.freeCompilerArgs += listOf("-include-binary", "$rootDir/native/build/linux/libsecp256k1.a")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ios {
|
iosX64 {
|
||||||
|
secp256k1CInterop("ios")
|
||||||
|
}
|
||||||
|
|
||||||
|
iosArm64 {
|
||||||
|
secp256k1CInterop("ios")
|
||||||
|
}
|
||||||
|
|
||||||
|
iosSimulatorArm64 {
|
||||||
secp256k1CInterop("ios")
|
secp256k1CInterop("ios")
|
||||||
compilations["main"].defaultSourceSet.dependsOn(nativeMain)
|
|
||||||
// https://youtrack.jetbrains.com/issue/KT-39396
|
|
||||||
compilations["main"].kotlinOptions.freeCompilerArgs += listOf("-include-binary", "$rootDir/native/build/ios/libsecp256k1.a")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets.all {
|
sourceSets.all {
|
||||||
@ -80,9 +82,9 @@ allprojects {
|
|||||||
val currentOs = OperatingSystem.current()
|
val currentOs = OperatingSystem.current()
|
||||||
val targets = when {
|
val targets = when {
|
||||||
currentOs.isLinux -> listOf()
|
currentOs.isLinux -> listOf()
|
||||||
currentOs.isMacOsX -> listOf("linux")
|
currentOs.isMacOsX -> listOf("linuxX64")
|
||||||
currentOs.isWindows -> listOf("linux")
|
currentOs.isWindows -> listOf("linuxX64")
|
||||||
else -> listOf("linux")
|
else -> listOf("linuxX64")
|
||||||
}.mapNotNull { kotlin.targets.findByName(it) as? KotlinNativeTarget }
|
}.mapNotNull { kotlin.targets.findByName(it) as? KotlinNativeTarget }
|
||||||
|
|
||||||
configure(targets) {
|
configure(targets) {
|
||||||
|
@ -6,11 +6,10 @@ import fr.acinq.secp256k1.NativeSecp256k1
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public object NativeSecp256k1AndroidLoader {
|
public object NativeSecp256k1AndroidLoader {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun load(): Secp256k1 {
|
public fun load(): Secp256k1 {
|
||||||
try {
|
try {
|
||||||
System.loadLibrary("secp256k1-jni")
|
System.loadLibrary("secp256k1-jni")
|
||||||
return NativeSecp256k1
|
return NativeSecp256k1
|
||||||
@ -27,5 +26,4 @@ public object NativeSecp256k1AndroidLoader {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,34 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_TYPE_CONTEXT
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_TYPE_CONTEXT 1L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_TYPE_COMPRESSION
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_TYPE_COMPRESSION 2L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_BIT_CONTEXT_VERIFY
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_BIT_CONTEXT_VERIFY 256L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_BIT_CONTEXT_SIGN
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_BIT_CONTEXT_SIGN 512L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_BIT_COMPRESSION
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_FLAGS_BIT_COMPRESSION 256L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_CONTEXT_VERIFY
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_CONTEXT_VERIFY 257L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_CONTEXT_SIGN
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_CONTEXT_SIGN 513L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_CONTEXT_NONE
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_CONTEXT_NONE 1L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_EC_COMPRESSED
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_EC_COMPRESSED 258L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_EC_UNCOMPRESSED
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_EC_UNCOMPRESSED 2L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_PUBLIC_NONCE_SIZE 66L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SECRET_NONCE_SIZE 132L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_KEYAGG_CACHE_SIZE 197L
|
||||||
|
#undef fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE
|
||||||
|
#define fr_acinq_secp256k1_Secp256k1CFunctions_SECP256K1_MUSIG_SESSION_SIZE 133L
|
||||||
/*
|
/*
|
||||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
* Method: secp256k1_context_create
|
* Method: secp256k1_context_create
|
||||||
@ -167,6 +195,78 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
|
|||||||
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1schnorrsig_1verify
|
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1schnorrsig_1verify
|
||||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray);
|
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* 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 *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* Method: secp256k1_musig_nonce_agg
|
||||||
|
* Signature: (J[[B)[B
|
||||||
|
*/
|
||||||
|
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1nonce_1agg
|
||||||
|
(JNIEnv *, jclass, jlong, jobjectArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* Method: secp256k1_musig_pubkey_agg
|
||||||
|
* Signature: (J[[B[B)[B
|
||||||
|
*/
|
||||||
|
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1agg
|
||||||
|
(JNIEnv *, jclass, jlong, jobjectArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* Method: secp256k1_musig_pubkey_ec_tweak_add
|
||||||
|
* Signature: (J[B[B)[B
|
||||||
|
*/
|
||||||
|
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1pubkey_1ec_1tweak_1add
|
||||||
|
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* 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 *, jclass, jlong, jbyteArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* 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 *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* Method: secp256k1_musig_partial_sign
|
||||||
|
* Signature: (J[B[B[B[B)[B
|
||||||
|
*/
|
||||||
|
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1musig_1partial_1sign
|
||||||
|
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* 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 *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||||
|
* 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 *, jclass, jlong, jbyteArray, jobjectArray);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,14 @@ public class Secp256k1CFunctions {
|
|||||||
public static final int SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION);
|
public static final int SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION);
|
||||||
public static final int SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION);
|
public static final int SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION);
|
||||||
|
|
||||||
|
public static final int SECP256K1_MUSIG_PUBLIC_NONCE_SIZE = 66;
|
||||||
|
|
||||||
|
public static final int SECP256K1_MUSIG_SECRET_NONCE_SIZE = 132;
|
||||||
|
|
||||||
|
public static final int SECP256K1_MUSIG_KEYAGG_CACHE_SIZE = 197;
|
||||||
|
|
||||||
|
public static final int SECP256K1_MUSIG_SESSION_SIZE = 133;
|
||||||
|
|
||||||
public static native long secp256k1_context_create(int flags);
|
public static native long secp256k1_context_create(int flags);
|
||||||
|
|
||||||
public static native void secp256k1_context_destroy(long ctx);
|
public static native void secp256k1_context_destroy(long ctx);
|
||||||
@ -68,4 +76,22 @@ public class Secp256k1CFunctions {
|
|||||||
public static native byte[] secp256k1_schnorrsig_sign(long ctx, byte[] msg, byte[] seckey, byte[] aux_rand32);
|
public static native byte[] secp256k1_schnorrsig_sign(long ctx, byte[] msg, byte[] seckey, byte[] aux_rand32);
|
||||||
|
|
||||||
public static native int secp256k1_schnorrsig_verify(long ctx, byte[] sig, byte[] msg, byte[] pubkey);
|
public static native int secp256k1_schnorrsig_verify(long ctx, byte[] sig, byte[] msg, byte[] pubkey);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_nonce_gen(long ctx, byte[] session_id32, byte[] seckey, byte[] pubkey, byte[] msg32, byte[] keyagg_cache, byte[] extra_input32);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_nonce_agg(long ctx, byte[][] nonces);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_pubkey_agg(long ctx, byte[][] pubkeys, byte[] keyagg_cache);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_pubkey_ec_tweak_add(long ctx, byte[] keyagg_cache, byte[] tweak32);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_pubkey_xonly_tweak_add(long ctx, byte[] keyagg_cache, byte[] tweak32);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_nonce_process(long ctx, byte[] aggnonce, byte[] msg32, byte[] keyagg_cache, byte[] adaptor);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_partial_sign(long ctx, byte[] secnonce, byte[] privkey, byte[] keyagg_cache, byte[] session);
|
||||||
|
|
||||||
|
public static native int secp256k1_musig_partial_sig_verify(long ctx, byte[] psig, byte[] pubnonce, byte[] pubkey, byte[] keyagg_cache, byte[] session);
|
||||||
|
|
||||||
|
public static native byte[] secp256k1_musig_partial_sig_agg(long ctx, byte[] session, byte[][] psigs);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,42 @@ public object NativeSecp256k1 : Secp256k1 {
|
|||||||
return Secp256k1CFunctions.secp256k1_schnorrsig_sign(Secp256k1Context.getContext(), data, sec, auxrand32)
|
return Secp256k1CFunctions.secp256k1_schnorrsig_sign(Secp256k1Context.getContext(), data, sec, auxrand32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun musigNonceGen(session_id32: ByteArray, seckey: ByteArray?, pubkey: ByteArray, msg32: ByteArray?, keyagg_cache: ByteArray?, extra_input32: ByteArray?): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_nonce_gen(Secp256k1Context.getContext(), session_id32, seckey, pubkey, msg32, keyagg_cache, extra_input32)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigNonceAgg(pubnonces: Array<ByteArray>): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_nonce_agg(Secp256k1Context.getContext(), pubnonces)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPubkeyAdd(pubkeys: Array<ByteArray>, keyagg_cache: ByteArray?): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_pubkey_agg(Secp256k1Context.getContext(), pubkeys, keyagg_cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPubkeyTweakAdd(keyagg_cache: ByteArray, tweak32: ByteArray): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_pubkey_ec_tweak_add(Secp256k1Context.getContext(), keyagg_cache, tweak32)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPubkeyXonlyTweakAdd(keyagg_cache: ByteArray, tweak32: ByteArray): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_pubkey_xonly_tweak_add(Secp256k1Context.getContext(), keyagg_cache, tweak32)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigNonceProcess(aggnonce: ByteArray, msg32: ByteArray, keyagg_cache: ByteArray, adaptor: ByteArray?): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_nonce_process(Secp256k1Context.getContext(), aggnonce, msg32, keyagg_cache, adaptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPartialSign(secnonce: ByteArray, privkey: ByteArray, keyagg_cache: ByteArray, session: ByteArray): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_partial_sign(Secp256k1Context.getContext(), secnonce, privkey, keyagg_cache, session)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPartialSigVerify(psig: ByteArray, pubnonce: ByteArray, pubkey: ByteArray, keyagg_cache: ByteArray, session: ByteArray): Int {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_partial_sig_verify(Secp256k1Context.getContext(), psig, pubnonce, pubkey, keyagg_cache, session)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPartialSigAgg(session: ByteArray, psigs: Array<ByteArray>): ByteArray {
|
||||||
|
return Secp256k1CFunctions.secp256k1_musig_partial_sig_agg(Secp256k1Context.getContext(), session, psigs)
|
||||||
|
}
|
||||||
|
|
||||||
override fun cleanup() {
|
override fun cleanup() {
|
||||||
return Secp256k1CFunctions.secp256k1_context_destroy(Secp256k1Context.getContext())
|
return Secp256k1CFunctions.secp256k1_context_destroy(Secp256k1Context.getContext())
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export STRIP=$ANDROID_NDK/toolchains/llvm/prebuilt/$TOOLCHAIN/bin/llvm-strip
|
|||||||
cd secp256k1
|
cd secp256k1
|
||||||
|
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure CFLAGS=-fpic --host=$TARGET --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no
|
./configure CFLAGS=-fpic --host=$TARGET --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-module-musig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no
|
||||||
make clean
|
make clean
|
||||||
make
|
make
|
||||||
|
|
||||||
|
@ -6,10 +6,13 @@ cp xconfigure.sh secp256k1
|
|||||||
cd secp256k1
|
cd secp256k1
|
||||||
|
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
sh xconfigure.sh --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no
|
sh xconfigure.sh --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-module-musig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no
|
||||||
|
|
||||||
mkdir -p ../build/ios
|
mkdir -p ../build/ios
|
||||||
cp -v _build/universal/* ../build/ios/
|
cp -v _build/universal/ios/* ../build/ios/
|
||||||
|
|
||||||
|
mkdir -p ../build/iosSimulatorArm64
|
||||||
|
cp -v _build/universal/iosSimulatorArm64/* ../build/iosSimulatorArm64/
|
||||||
|
|
||||||
rm -rf _build
|
rm -rf _build
|
||||||
make clean
|
make clean
|
||||||
|
@ -23,7 +23,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure $CONF_OPTS --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no
|
./configure $CONF_OPTS --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-module-musig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no
|
||||||
make clean
|
make clean
|
||||||
make
|
make
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 1ad5185cd42c0636104129fcc9f6a4bf9c67cc40
|
Subproject commit eaf1e78d2d3feee3bd9f349d2f0b98aac0204604
|
@ -69,9 +69,22 @@ HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=${MIN_IOS_VERSION} -isysro
|
|||||||
CHOST="x86_64-apple-darwin"
|
CHOST="x86_64-apple-darwin"
|
||||||
Build "$@"
|
Build "$@"
|
||||||
|
|
||||||
|
## Build for iphone M1/M2/Mx simulators
|
||||||
|
SDK="iphonesimulator"
|
||||||
|
PLATFORM="arm64-sim"
|
||||||
|
PLATFORM_SIM_ARM=${PLATFORM}
|
||||||
|
ARCH_FLAGS="-arch arm64"
|
||||||
|
HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=${MIN_IOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)"
|
||||||
|
CHOST="arm-apple-darwin"
|
||||||
|
Build "$@"
|
||||||
|
|
||||||
# Create universal binary
|
# Create universal binary
|
||||||
cd "${PLATFORMS}/${PLATFORM_ARM}/lib"
|
cd "${PLATFORMS}/${PLATFORM_ARM}/lib"
|
||||||
LIB_NAME=`find . -iname *.a`
|
LIB_NAME=`find . -iname *.a`
|
||||||
cd -
|
cd -
|
||||||
mkdir -p "${UNIVERSAL}" &> /dev/null
|
mkdir -p "${UNIVERSAL}/ios" &> /dev/null
|
||||||
lipo -create -output "${UNIVERSAL}/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ARM}/lib/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ISIM}/lib/${LIB_NAME}"
|
mkdir -p "${UNIVERSAL}/iosSimulatorArm64" &> /dev/null
|
||||||
|
lipo -create -output "${UNIVERSAL}/ios/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ARM}/lib/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ISIM}/lib/${LIB_NAME}"
|
||||||
|
|
||||||
|
# create a specific library for arm64 simulator: it cannot be included in the lib above which already contains an arm64 lib
|
||||||
|
lipo -create -output "${UNIVERSAL}/iosSimulatorArm64/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_SIM_ARM}/lib/${LIB_NAME}"
|
@ -21,9 +21,9 @@ mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/conte
|
|||||||
-Djavadoc=$ARTIFACT_ID_BASE-$VERSION-javadoc.jar
|
-Djavadoc=$ARTIFACT_ID_BASE-$VERSION-javadoc.jar
|
||||||
popd
|
popd
|
||||||
pushd .
|
pushd .
|
||||||
for i in iosarm64 iosx64 jni-android jni-common jni-jvm-darwin jni-jvm-extract jni-jvm-linux jni-jvm-mingw jni-jvm jvm linux; do
|
for i in iosarm64 iossimulatorarm64 iosx64 jni-android jni-common jni-jvm-darwin jni-jvm-extract jni-jvm-linux jni-jvm-mingw jni-jvm jvm linuxx64; do
|
||||||
cd fr/acinq/secp256k1/secp256k1-kmp-$i/$VERSION
|
cd fr/acinq/secp256k1/secp256k1-kmp-$i/$VERSION
|
||||||
if [ $i == iosarm64 ] || [ $i == iosx64 ]; then
|
if [ $i == iosarm64 ] || [ $i == iossimulatorarm64 ] || [ $i == iosx64 ]; then
|
||||||
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
|
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
|
||||||
-DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
|
-DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
|
||||||
-Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.klib \
|
-Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.klib \
|
||||||
@ -32,7 +32,7 @@ for i in iosarm64 iosx64 jni-android jni-common jni-jvm-darwin jni-jvm-extract j
|
|||||||
-Dclassifiers=metadata,,cinterop-libsecp256k1 \
|
-Dclassifiers=metadata,,cinterop-libsecp256k1 \
|
||||||
-Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \
|
-Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \
|
||||||
-Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar
|
-Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar
|
||||||
elif [ $i == linux ]; then
|
elif [ $i == linuxx64 ]; then
|
||||||
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
|
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
|
||||||
-DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
|
-DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
|
||||||
-Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.klib \
|
-Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.klib \
|
||||||
|
@ -153,6 +153,25 @@ public interface Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun musigNonceGen(session_id32: ByteArray, seckey: ByteArray?, pubkey: ByteArray, msg32: ByteArray?, keyagg_cache: ByteArray?, extra_input32: ByteArray?): ByteArray
|
||||||
|
|
||||||
|
public fun musigNonceAgg(pubnonces: Array<ByteArray>): ByteArray
|
||||||
|
|
||||||
|
public fun musigPubkeyAdd(pubkeys: Array<ByteArray>, keyagg_cache: ByteArray?): ByteArray
|
||||||
|
|
||||||
|
public fun musigPubkeyTweakAdd(keyagg_cache: ByteArray, tweak32: ByteArray): ByteArray
|
||||||
|
|
||||||
|
public fun musigPubkeyXonlyTweakAdd(keyagg_cache: ByteArray, tweak32: ByteArray): ByteArray
|
||||||
|
|
||||||
|
public fun musigNonceProcess(aggnonce: ByteArray, msg32: ByteArray, keyagg_cache: ByteArray, adaptor: ByteArray?): ByteArray
|
||||||
|
|
||||||
|
public fun musigPartialSign(secnonce: ByteArray, privkey: ByteArray, keyagg_cache: ByteArray, session: ByteArray): ByteArray
|
||||||
|
|
||||||
|
public fun musigPartialSigVerify(psig: ByteArray, pubnonce: ByteArray, pubkey: ByteArray, keyagg_cache: ByteArray, session: ByteArray): Int
|
||||||
|
|
||||||
|
public fun musigPartialSigAgg(session: ByteArray, psigs: Array<ByteArray>): ByteArray
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the secp256k1 context from dynamic memory.
|
* Delete the secp256k1 context from dynamic memory.
|
||||||
*/
|
*/
|
||||||
@ -161,6 +180,13 @@ public interface Secp256k1 {
|
|||||||
public companion object : Secp256k1 by getSecpk256k1() {
|
public companion object : Secp256k1 by getSecpk256k1() {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun get(): Secp256k1 = this
|
public fun get(): Secp256k1 = this
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
public const val MUSIG2_SECRET_NONCE_SIZE: Int = 132
|
||||||
|
public const val MUSIG2_PUBLIC_NONCE_SIZE: Int = 66
|
||||||
|
public const val MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE: Int = 197
|
||||||
|
public const val MUSIG2_PUBLIC_SESSION_SIZE: Int = 133
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
package = secp256k1
|
package = secp256k1
|
||||||
|
|
||||||
headers = secp256k1.h secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h
|
headers = secp256k1.h secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h secp256k1_musig.h
|
||||||
headerFilter = secp256k1/** secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h secp256k1.h
|
headerFilter = secp256k1/** secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h secp256k1_musig.h secp256k1.h
|
||||||
|
|
||||||
libraryPaths.linux = c/secp256k1/build/linux/
|
staticLibraries.linux = libsecp256k1.a
|
||||||
|
libraryPaths.linux = c/secp256k1/build/linux/ native/build/linux/ native/build/darwin/
|
||||||
linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib
|
linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib
|
||||||
|
|
||||||
libraryPaths.ios = c/secp256k1/build/ios/ /usr/local/lib
|
staticLibraries.ios = libsecp256k1.a
|
||||||
|
libraryPaths.ios_x64 = c/secp256k1/build/ios/ /usr/local/lib native/build/ios/
|
||||||
|
libraryPaths.ios_arm64 = c/secp256k1/build/ios/ /usr/local/lib native/build/ios/
|
||||||
|
libraryPaths.ios_simulator_arm64 = c/secp256k1/build/ios/ /usr/local/lib native/build/iosSimulatorArm64/
|
||||||
linkerOpts.ios = -framework Security -framework Foundation
|
linkerOpts.ios = -framework Security -framework Foundation
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package fr.acinq.secp256k1
|
package fr.acinq.secp256k1
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
|
import platform.posix.memcpy
|
||||||
import platform.posix.size_tVar
|
import platform.posix.size_tVar
|
||||||
import secp256k1.*
|
import secp256k1.*
|
||||||
|
|
||||||
@OptIn(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalForeignApi::class)
|
||||||
public object Secp256k1Native : Secp256k1 {
|
public object Secp256k1Native : Secp256k1 {
|
||||||
|
|
||||||
private val ctx: CPointer<secp256k1_context> by lazy {
|
private val ctx: CPointer<secp256k1_context> by lazy {
|
||||||
@ -40,6 +41,20 @@ public object Secp256k1Native : Secp256k1 {
|
|||||||
return pub
|
return pub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun MemScope.allocPublicNonce(pubnonce: ByteArray): secp256k1_musig_pubnonce {
|
||||||
|
val nat = toNat(pubnonce)
|
||||||
|
val nPubnonce = alloc<secp256k1_musig_pubnonce>()
|
||||||
|
secp256k1_musig_pubnonce_parse(ctx, nPubnonce.ptr, nat).requireSuccess("secp256k1_musig_pubnonce_parse() failed")
|
||||||
|
return nPubnonce
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MemScope.allocPartialSig(psig: ByteArray): secp256k1_musig_partial_sig {
|
||||||
|
val nat = toNat(psig)
|
||||||
|
val nPsig = alloc<secp256k1_musig_partial_sig>()
|
||||||
|
secp256k1_musig_partial_sig_parse(ctx, nPsig.ptr, nat).requireSuccess("secp256k1_musig_partial_sig_parse() failed")
|
||||||
|
return nPsig
|
||||||
|
}
|
||||||
|
|
||||||
private fun MemScope.serializePubkey(pubkey: secp256k1_pubkey): ByteArray {
|
private fun MemScope.serializePubkey(pubkey: secp256k1_pubkey): ByteArray {
|
||||||
val serialized = allocArray<UByteVar>(65)
|
val serialized = allocArray<UByteVar>(65)
|
||||||
val outputLen = alloc<size_tVar>()
|
val outputLen = alloc<size_tVar>()
|
||||||
@ -48,6 +63,24 @@ public object Secp256k1Native : Secp256k1 {
|
|||||||
return serialized.readBytes(outputLen.value.convert())
|
return serialized.readBytes(outputLen.value.convert())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun MemScope.serializeXonlyPubkey(pubkey: secp256k1_xonly_pubkey): ByteArray {
|
||||||
|
val serialized = allocArray<UByteVar>(32)
|
||||||
|
secp256k1_xonly_pubkey_serialize(ctx, serialized, pubkey.ptr).requireSuccess("secp256k1_xonly_pubkey_serialize() failed")
|
||||||
|
return serialized.readBytes(32)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MemScope.serializePubnonce(pubnonce: secp256k1_musig_pubnonce): ByteArray {
|
||||||
|
val serialized = allocArray<UByteVar>(Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
secp256k1_musig_pubnonce_serialize(ctx, serialized, pubnonce.ptr).requireSuccess("secp256k1_musig_pubnonce_serialize() failed")
|
||||||
|
return serialized.readBytes(Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MemScope.serializeAggnonce(aggnonce: secp256k1_musig_aggnonce): ByteArray {
|
||||||
|
val serialized = allocArray<UByteVar>(Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
secp256k1_musig_aggnonce_serialize(ctx, serialized, aggnonce.ptr).requireSuccess("secp256k1_musig_aggnonce_serialize() failed")
|
||||||
|
return serialized.readBytes(Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
private fun DeferScope.toNat(bytes: ByteArray): CPointer<UByteVar> {
|
private fun DeferScope.toNat(bytes: ByteArray): CPointer<UByteVar> {
|
||||||
val ubytes = bytes.asUByteArray()
|
val ubytes = bytes.asUByteArray()
|
||||||
val pinned = ubytes.pin()
|
val pinned = ubytes.pin()
|
||||||
@ -238,7 +271,7 @@ public object Secp256k1Native : Secp256k1 {
|
|||||||
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed")
|
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed")
|
||||||
val nData = toNat(data)
|
val nData = toNat(data)
|
||||||
val nSig = toNat(signature)
|
val nSig = toNat(signature)
|
||||||
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32, pubkey.ptr) == 1
|
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32u, pubkey.ptr) == 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,12 +290,163 @@ public object Secp256k1Native : Secp256k1 {
|
|||||||
return nSig.readBytes(64)
|
return nSig.readBytes(64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun musigNonceGen(session_id32: ByteArray, seckey: ByteArray?, pubkey: ByteArray, msg32: ByteArray?, keyagg_cache: ByteArray?, extra_input32: ByteArray?): ByteArray {
|
||||||
|
require(session_id32.size == 32)
|
||||||
|
seckey?.let { require(it.size == 32) }
|
||||||
|
msg32?.let { require(it.size == 32) }
|
||||||
|
keyagg_cache?.let { require(it.size == Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE) }
|
||||||
|
extra_input32?.let { require(it.size == 32) }
|
||||||
|
|
||||||
|
val nonce = memScoped {
|
||||||
|
val secret_nonce = alloc<secp256k1_musig_secnonce>()
|
||||||
|
val public_nonce = alloc<secp256k1_musig_pubnonce>()
|
||||||
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
|
val nKeyAggCache = keyagg_cache?.let {
|
||||||
|
val n = alloc<secp256k1_musig_keyagg_cache>()
|
||||||
|
memcpy(n.ptr, toNat(it), Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
n
|
||||||
|
}
|
||||||
|
secp256k1_musig_nonce_gen(ctx, secret_nonce.ptr, public_nonce.ptr, toNat(session_id32), seckey?.let { toNat(it) }, nPubkey.ptr, msg32?.let { toNat(it) },nKeyAggCache?.ptr, extra_input32?.let { toNat(it) }).requireSuccess("secp256k1_musig_nonce_gen() failed")
|
||||||
|
val nPubnonce = allocArray<UByteVar>(Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
secp256k1_musig_pubnonce_serialize(ctx, nPubnonce, public_nonce.ptr).requireSuccess("secp256k1_musig_pubnonce_serialize failed")
|
||||||
|
secret_nonce.ptr.readBytes(Secp256k1.MUSIG2_SECRET_NONCE_SIZE) + nPubnonce.readBytes(Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
}
|
||||||
|
return nonce
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigNonceAgg(pubnonces: Array<ByteArray>): ByteArray {
|
||||||
|
require(pubnonces.isNotEmpty())
|
||||||
|
pubnonces.forEach { require(it.size == Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE) }
|
||||||
|
memScoped {
|
||||||
|
val nPubnonces = pubnonces.map { allocPublicNonce(it).ptr }
|
||||||
|
val combined = alloc<secp256k1_musig_aggnonce>()
|
||||||
|
secp256k1_musig_nonce_agg(ctx, combined.ptr, nPubnonces.toCValues(), pubnonces.size.convert()).requireSuccess("secp256k1_musig_nonce_agg() failed")
|
||||||
|
return serializeAggnonce(combined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPubkeyAdd(pubkeys: Array<ByteArray>, keyagg_cache: ByteArray?): ByteArray {
|
||||||
|
require(pubkeys.isNotEmpty())
|
||||||
|
pubkeys.forEach { require(it.size == 33 || it.size == 65) }
|
||||||
|
keyagg_cache?.let { require(it.size == Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE) }
|
||||||
|
memScoped {
|
||||||
|
val nPubkeys = pubkeys.map { allocPublicKey(it).ptr }
|
||||||
|
val combined = alloc<secp256k1_xonly_pubkey>()
|
||||||
|
val nKeyAggCache = keyagg_cache?.let {
|
||||||
|
val n = alloc<secp256k1_musig_keyagg_cache>()
|
||||||
|
memcpy(n.ptr, toNat(it), Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
n
|
||||||
|
}
|
||||||
|
secp256k1_musig_pubkey_agg(ctx, combined.ptr, nKeyAggCache?.ptr, nPubkeys.toCValues(), pubkeys.size.convert()).requireSuccess("secp256k1_musig_nonce_agg() failed")
|
||||||
|
val agg = serializeXonlyPubkey(combined)
|
||||||
|
keyagg_cache?.let { blob -> nKeyAggCache?.let { memcpy(toNat(blob), it.ptr, Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong()) } }
|
||||||
|
return agg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPubkeyTweakAdd(keyagg_cache: ByteArray, tweak32: ByteArray): ByteArray {
|
||||||
|
require(keyagg_cache.size == Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE)
|
||||||
|
require(tweak32.size == 32)
|
||||||
|
memScoped {
|
||||||
|
val nKeyAggCache = alloc<secp256k1_musig_keyagg_cache>()
|
||||||
|
memcpy(nKeyAggCache.ptr, toNat(keyagg_cache), Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
val nPubkey = alloc<secp256k1_pubkey>()
|
||||||
|
secp256k1_musig_pubkey_ec_tweak_add(ctx, nPubkey.ptr, nKeyAggCache.ptr, toNat(tweak32)).requireSuccess("secp256k1_musig_pubkey_ec_tweak_add() failed")
|
||||||
|
memcpy(toNat(keyagg_cache), nKeyAggCache.ptr, Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
return serializePubkey(nPubkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPubkeyXonlyTweakAdd(keyagg_cache: ByteArray, tweak32: ByteArray): ByteArray {
|
||||||
|
require(keyagg_cache.size == Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE)
|
||||||
|
require(tweak32.size == 32)
|
||||||
|
memScoped {
|
||||||
|
val nKeyAggCache = alloc<secp256k1_musig_keyagg_cache>()
|
||||||
|
memcpy(nKeyAggCache.ptr, toNat(keyagg_cache), Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
val nPubkey = alloc<secp256k1_pubkey>()
|
||||||
|
secp256k1_musig_pubkey_xonly_tweak_add(ctx, nPubkey.ptr, nKeyAggCache.ptr, toNat(tweak32)).requireSuccess("secp256k1_musig_pubkey_xonly_tweak_add() failed")
|
||||||
|
memcpy(toNat(keyagg_cache), nKeyAggCache.ptr, Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
return serializePubkey(nPubkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigNonceProcess(aggnonce: ByteArray, msg32: ByteArray, keyagg_cache: ByteArray, adaptor: ByteArray?): ByteArray {
|
||||||
|
require(aggnonce.size == Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
require(keyagg_cache.size == Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE)
|
||||||
|
require(msg32.size == 32)
|
||||||
|
memScoped {
|
||||||
|
val nKeyAggCache = alloc<secp256k1_musig_keyagg_cache>()
|
||||||
|
memcpy(nKeyAggCache.ptr, toNat(keyagg_cache), Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
val nSession = alloc<secp256k1_musig_session>()
|
||||||
|
val nAggnonce = alloc<secp256k1_musig_aggnonce>()
|
||||||
|
secp256k1_musig_aggnonce_parse(ctx, nAggnonce.ptr, toNat(aggnonce)).requireSuccess("secp256k1_musig_aggnonce_parse() failed")
|
||||||
|
secp256k1_musig_nonce_process(ctx, nSession.ptr, nAggnonce.ptr, toNat(msg32), nKeyAggCache.ptr).requireSuccess("secp256k1_musig_nonce_process() failed")
|
||||||
|
val session = ByteArray(Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE)
|
||||||
|
memcpy(toNat(session), nSession.ptr, Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE.toULong())
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPartialSign(secnonce: ByteArray, privkey: ByteArray, keyagg_cache: ByteArray, session: ByteArray): ByteArray {
|
||||||
|
require(secnonce.size == Secp256k1.MUSIG2_SECRET_NONCE_SIZE)
|
||||||
|
require(privkey.size == 32)
|
||||||
|
require(keyagg_cache.size == Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE)
|
||||||
|
require(session.size == Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE)
|
||||||
|
|
||||||
|
memScoped {
|
||||||
|
val nSecnonce = alloc<secp256k1_musig_secnonce>()
|
||||||
|
memcpy(nSecnonce.ptr, toNat(secnonce), Secp256k1.MUSIG2_SECRET_NONCE_SIZE.toULong())
|
||||||
|
val nKeypair = alloc<secp256k1_keypair>()
|
||||||
|
secp256k1_keypair_create(ctx, nKeypair.ptr, toNat(privkey))
|
||||||
|
val nPsig = alloc<secp256k1_musig_partial_sig>()
|
||||||
|
val nKeyAggCache = alloc<secp256k1_musig_keyagg_cache>()
|
||||||
|
memcpy(nKeyAggCache.ptr, toNat(keyagg_cache), Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
val nSession = alloc<secp256k1_musig_session>()
|
||||||
|
memcpy(nSession.ptr, toNat(session), Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE.toULong())
|
||||||
|
secp256k1_musig_partial_sign(ctx, nPsig.ptr, nSecnonce.ptr, nKeypair.ptr, nKeyAggCache.ptr, nSession.ptr).requireSuccess("secp256k1_musig_partial_sign failed")
|
||||||
|
val psig = ByteArray(32)
|
||||||
|
secp256k1_musig_partial_sig_serialize(ctx, toNat(psig), nPsig.ptr).requireSuccess("secp256k1_musig_partial_sig_serialize() failed")
|
||||||
|
return psig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPartialSigVerify(psig: ByteArray, pubnonce: ByteArray, pubkey: ByteArray, keyagg_cache: ByteArray, session: ByteArray): Int {
|
||||||
|
require(psig.size == 32)
|
||||||
|
require(pubnonce.size == Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
|
||||||
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
|
require(keyagg_cache.size == Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE)
|
||||||
|
require(session.size == Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE)
|
||||||
|
|
||||||
|
memScoped {
|
||||||
|
val nPSig = allocPartialSig(psig)
|
||||||
|
val nPubnonce = allocPublicNonce(pubnonce)
|
||||||
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
|
val nKeyAggCache = alloc<secp256k1_musig_keyagg_cache>()
|
||||||
|
memcpy(nKeyAggCache.ptr, toNat(keyagg_cache), Secp256k1.MUSIG2_PUBLIC_KEYAGG_CACHE_SIZE.toULong())
|
||||||
|
val nSession = alloc<secp256k1_musig_session>()
|
||||||
|
memcpy(nSession.ptr, toNat(session), Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE.toULong())
|
||||||
|
return secp256k1_musig_partial_sig_verify(ctx, nPSig.ptr, nPubnonce.ptr, nPubkey.ptr, nKeyAggCache.ptr, nSession.ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun musigPartialSigAgg(session: ByteArray, psigs: Array<ByteArray>): ByteArray {
|
||||||
|
require(session.size == Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE)
|
||||||
|
require(psigs.isNotEmpty())
|
||||||
|
psigs.forEach { require(it.size == 32) }
|
||||||
|
memScoped {
|
||||||
|
val nSession = alloc<secp256k1_musig_session>()
|
||||||
|
memcpy(nSession.ptr, toNat(session), Secp256k1.MUSIG2_PUBLIC_SESSION_SIZE.toULong())
|
||||||
|
val nPsigs = psigs.map { allocPartialSig(it).ptr }
|
||||||
|
val sig64 = ByteArray(64)
|
||||||
|
secp256k1_musig_partial_sig_agg(ctx, toNat(sig64), nSession.ptr, nPsigs.toCValues(), psigs.size.convert()).requireSuccess("secp256k1_musig_partial_sig_agg() failed")
|
||||||
|
return sig64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override fun cleanup() {
|
public override fun cleanup() {
|
||||||
secp256k1_context_destroy(ctx)
|
secp256k1_context_destroy(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal actual fun getSecpk256k1(): Secp256k1 = Secp256k1Native
|
internal actual fun getSecpk256k1(): Secp256k1 = Secp256k1Native
|
||||||
|
@ -36,14 +36,14 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (includeAndroid) {
|
if (includeAndroid) {
|
||||||
android {
|
androidTarget {
|
||||||
compilations.all {
|
compilations.all {
|
||||||
kotlinOptions.jvmTarget = "1.8"
|
kotlinOptions.jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
sourceSets["androidMain"].dependencies {
|
sourceSets["androidMain"].dependencies {
|
||||||
implementation(project(":jni:android"))
|
implementation(project(":jni:android"))
|
||||||
}
|
}
|
||||||
sourceSets["androidTest"].dependencies {
|
sourceSets["androidUnitTest"].dependencies {
|
||||||
implementation(kotlin("test-junit"))
|
implementation(kotlin("test-junit"))
|
||||||
implementation("androidx.test.ext:junit:1.1.2")
|
implementation("androidx.test.ext:junit:1.1.2")
|
||||||
implementation("androidx.test.espresso:espresso-core:3.3.0")
|
implementation("androidx.test.espresso:espresso-core:3.3.0")
|
||||||
@ -51,17 +51,18 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
linuxX64("linux")
|
linuxX64()
|
||||||
|
iosX64()
|
||||||
ios()
|
iosArm64()
|
||||||
|
iosSimulatorArm64()
|
||||||
}
|
}
|
||||||
|
|
||||||
val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true
|
val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true
|
||||||
if (includeAndroid) {
|
if (includeAndroid) {
|
||||||
extensions.configure<com.android.build.gradle.LibraryExtension>("android") {
|
extensions.configure<com.android.build.gradle.LibraryExtension>("android") {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
compileSdkVersion(30)
|
compileSdk =30
|
||||||
minSdkVersion(21)
|
minSdk = 21
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,6 +352,119 @@ class Secp256k1Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMusig2GenerateNonce() {
|
||||||
|
val pubkey = Hex.decode("02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9")
|
||||||
|
val sessionId = Hex.decode("0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F")
|
||||||
|
val nonce = Secp256k1.musigNonceGen(sessionId, null, pubkey, null, null, null)
|
||||||
|
val pubnonce = Hex.encode(nonce.copyOfRange(132, 132 + 66)).uppercase()
|
||||||
|
assertEquals("02C96E7CB1E8AA5DAC64D872947914198F607D90ECDE5200DE52978AD5DED63C000299EC5117C2D29EDEE8A2092587C3909BE694D5CFF0667D6C02EA4059F7CD9786", pubnonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMusig2AggregateNonce() {
|
||||||
|
val nonces = listOf(
|
||||||
|
"020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E66603BA47FBC1834437B3212E89A84D8425E7BF12E0245D98262268EBDCB385D50641",
|
||||||
|
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833",
|
||||||
|
"020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E6660279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||||
|
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60379BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||||
|
"04FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833",
|
||||||
|
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B831",
|
||||||
|
"03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A602FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30"
|
||||||
|
).map { Hex.decode(it) }
|
||||||
|
val agg1 = Secp256k1.musigNonceAgg(arrayOf(nonces[0], nonces[1]))
|
||||||
|
assertEquals("035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B024725377345BDE0E9C33AF3C43C0A29A9249F2F2956FA8CFEB55C8573D0262DC8", Hex.encode(agg1).uppercase())
|
||||||
|
|
||||||
|
val agg2 = Secp256k1.musigNonceAgg(arrayOf(nonces[2], nonces[3]))
|
||||||
|
assertEquals("035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B000000000000000000000000000000000000000000000000000000000000000000", Hex.encode(agg2).uppercase())
|
||||||
|
|
||||||
|
assertFails {
|
||||||
|
Secp256k1.musigNonceAgg(arrayOf(nonces[0], nonces[4]))
|
||||||
|
}
|
||||||
|
assertFails {
|
||||||
|
Secp256k1.musigNonceAgg(arrayOf(nonces[5], nonces[1]))
|
||||||
|
}
|
||||||
|
assertFails {
|
||||||
|
Secp256k1.musigNonceAgg(arrayOf(nonces[6], nonces[1]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMusig2AggregatePubkey() {
|
||||||
|
val pubkeys = listOf(
|
||||||
|
"02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
|
||||||
|
"03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
|
||||||
|
"023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66",
|
||||||
|
"020000000000000000000000000000000000000000000000000000000000000005",
|
||||||
|
"02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30",
|
||||||
|
"04F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
|
||||||
|
"03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9"
|
||||||
|
|
||||||
|
).map { Hex.decode(it) }
|
||||||
|
|
||||||
|
val agg1 = Secp256k1.musigPubkeyAdd(arrayOf(pubkeys[0], pubkeys[1], pubkeys[2]), null)
|
||||||
|
assertEquals("90539EEDE565F5D054F32CC0C220126889ED1E5D193BAF15AEF344FE59D4610C", Hex.encode(agg1).uppercase())
|
||||||
|
val cache = ByteArray(197)
|
||||||
|
val agg2 = Secp256k1.musigPubkeyAdd(arrayOf(pubkeys[0], pubkeys[1], pubkeys[2]), cache)
|
||||||
|
assertEquals("90539EEDE565F5D054F32CC0C220126889ED1E5D193BAF15AEF344FE59D4610C", Hex.encode(agg2).uppercase())
|
||||||
|
|
||||||
|
val agg3 = Secp256k1.musigPubkeyAdd(arrayOf(pubkeys[2], pubkeys[1], pubkeys[0]), null)
|
||||||
|
assertEquals("6204DE8B083426DC6EAF9502D27024D53FC826BF7D2012148A0575435DF54B2B", Hex.encode(agg3).uppercase())
|
||||||
|
|
||||||
|
val agg4 = Secp256k1.musigPubkeyAdd(arrayOf(pubkeys[0], pubkeys[0], pubkeys[0]), null)
|
||||||
|
assertEquals("B436E3BAD62B8CD409969A224731C193D051162D8C5AE8B109306127DA3AA935", Hex.encode(agg4).uppercase())
|
||||||
|
|
||||||
|
val agg5 = Secp256k1.musigPubkeyAdd(arrayOf(pubkeys[0], pubkeys[0], pubkeys[1], pubkeys[1]), null)
|
||||||
|
assertEquals("69BC22BFA5D106306E48A20679DE1D7389386124D07571D0D872686028C26A3E", Hex.encode(agg5).uppercase())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMusig2TweakPubkeys() {
|
||||||
|
val pubkeys = listOf(
|
||||||
|
"031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
|
||||||
|
"024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
|
||||||
|
"02531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe337"
|
||||||
|
).map { Hex.decode(it) }.toTypedArray()
|
||||||
|
val cache = ByteArray(197)
|
||||||
|
val agg1 = Secp256k1.musigPubkeyAdd(pubkeys, cache)
|
||||||
|
assertEquals("b6d830642403fc82511aca5ff98a5e76fcef0f89bffc1aadbe78ee74cd5a5716", Hex.encode(agg1))
|
||||||
|
val agg2 = Secp256k1.musigPubkeyTweakAdd(cache, Hex.decode("7468697320636f756c64206265206120424950333220747765616b2e2e2e2e00"))
|
||||||
|
assertEquals("04791e4f22a21f19bd9798eceab92ad2ccc18f2d6660e91ae4c0709aaebf1aa9023701f468b0eddf8973495a5327f2169d9c6a50eb6a0f87c0fbee90a4067eb230", Hex.encode(agg2))
|
||||||
|
val agg3 = Secp256k1.musigPubkeyXonlyTweakAdd(cache, Hex.decode("7468697320636f756c64206265206120746170726f6f7420747765616b2e2e00"))
|
||||||
|
assertEquals("04537a081a8d32ff700ca86aaa77a423e9b8d1480938076b645c68ee39d263c93948026928799b2d942cb5851db397015b26b1759de1b9ab2c691ced64a2eef836", Hex.encode(agg3))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMusig2SigningSession() {
|
||||||
|
val privkeys = listOf(
|
||||||
|
"0101010101010101010101010101010101010101010101010101010101010101",
|
||||||
|
"0202020202020202020202020202020202020202020202020202020202020202",
|
||||||
|
).map { Hex.decode(it) }.toTypedArray()
|
||||||
|
val pubkeys = privkeys.map { Secp256k1.pubkeyCreate(it) }
|
||||||
|
|
||||||
|
val sessionId = Hex.decode("0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F")
|
||||||
|
val nonces = pubkeys.map { Secp256k1.musigNonceGen(sessionId, null, it, null, null, null) }
|
||||||
|
val secnonces = nonces.map { it.copyOfRange(0, 132) }
|
||||||
|
val pubnonces = nonces.map { it.copyOfRange(132, 132 + 66) }
|
||||||
|
val aggnonce = Secp256k1.musigNonceAgg(pubnonces.toTypedArray())
|
||||||
|
|
||||||
|
val caches = (0 until 2).map { ByteArray(197) }
|
||||||
|
val aggpubkey = Secp256k1.musigPubkeyAdd(pubkeys.toTypedArray(), caches[0])
|
||||||
|
Secp256k1.musigPubkeyAdd(pubkeys.toTypedArray(), caches[1])
|
||||||
|
|
||||||
|
val msg32 = Hex.decode("0303030303030303030303030303030303030303030303030303030303030303")
|
||||||
|
val sessions = (0 until 2).map { Secp256k1.musigNonceProcess(aggnonce, msg32, caches[it], null) }
|
||||||
|
val psigs = (0 until 2).map {
|
||||||
|
val psig = Secp256k1.musigPartialSign(secnonces[it], privkeys[it], caches[it], sessions[it])
|
||||||
|
val check = Secp256k1.musigPartialSigVerify(psig, pubnonces[it], pubkeys[it], caches[it], sessions[it])
|
||||||
|
assertEquals(1, check)
|
||||||
|
psig
|
||||||
|
}
|
||||||
|
val sig = Secp256k1.musigPartialSigAgg(sessions[0], psigs.toTypedArray())
|
||||||
|
val check = Secp256k1.verifySchnorr(sig, msg32, aggpubkey)
|
||||||
|
assertTrue(check)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInvalidArguments() {
|
fun testInvalidArguments() {
|
||||||
assertFails {
|
assertFails {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user