diff --git a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java index 41f0613..5c1814a 100644 --- a/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java +++ b/jni/src/main/java/fr/acinq/secp256k1/Secp256k1CFunctions.java @@ -107,13 +107,13 @@ public class Secp256k1CFunctions { public static native byte[] secp256k1_musig_partial_sig_agg(long ctx, byte[] session, byte[][] psigs); - public static native byte[][] secp256k1_frost_shares_gen(long ctx, byte[][] vss_commitment, byte[] pok64, byte[] seed32, int total_signers, byte[][] ids33); + public static native byte[][][] secp256k1_frost_shares_gen(long ctx, byte[] pok64, byte[] seed32, int threshold, int total_signers, byte[][] ids33); - public static native byte[][] secp256k1_frost_share_agg(long ctx, byte[][][] vss_commitments, byte[] id33); + public static native byte[][] secp256k1_frost_share_agg(long ctx, byte[][][] vss_commitments, int totalShareCount, int threshold, byte[] id33); public static native int secp256k1_frost_share_verify(long ctx, byte[] id33, byte[] share, byte[][] vss_commitment); - public static native byte[] secp256k1_frost_compute_pubshare(long ctx, byte[] id33, byte[][][] vss_commitments); + public static native byte[] secp256k1_frost_compute_pubshare(long ctx, int threshold, byte[] id33, byte[][][] vss_commitments, int totalSignersCount); public static native byte[] secp256k1_frost_pubkey_tweak(long ctx, byte[] public_key); diff --git a/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt b/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt index aabff3b..faced93 100644 --- a/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt +++ b/jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt @@ -130,30 +130,39 @@ public object NativeSecp256k1 : Secp256k1 { } override fun frostSharesGen( - vssCommitment: Array, pok64: ByteArray, seed32: ByteArray, + threshold: Int, totalSigners: Int, ids33: Array - ): Array { - return Secp256k1CFunctions.secp256k1_frost_shares_gen( + ): Pair, Array> { + val result = Secp256k1CFunctions.secp256k1_frost_shares_gen( Secp256k1Context.getContext(), - vssCommitment, pok64, seed32, + threshold, totalSigners, ids33 ) + + return Pair( + result[0], + result[1] + ) } override fun frostShareAggregate( totalShares: Array, vssCommitments: Array>, + totalShareCount: Int, + threshold: Int, id33: ByteArray ): Pair { val result = Secp256k1CFunctions.secp256k1_frost_share_agg( Secp256k1Context.getContext(), vssCommitments, + totalShareCount, + threshold, id33 ) return Pair( @@ -177,13 +186,17 @@ public object NativeSecp256k1 : Secp256k1 { } override fun frostComputePublicShare( + threshold: Int, id33: ByteArray, - vssCommitments: Array> + vssCommitments: Array>, + totalSignersCount: Int ): ByteArray { return Secp256k1CFunctions.secp256k1_frost_compute_pubshare( Secp256k1Context.getContext(), + threshold, id33, - vssCommitments + vssCommitments, + totalSignersCount ) } diff --git a/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt b/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt index 91fb7c9..496bb38 100644 --- a/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt +++ b/src/commonMain/kotlin/fr/acinq/secp256k1/Secp256k1.kt @@ -271,14 +271,14 @@ public interface Secp256k1 { */ public fun musigPartialSigAgg(session: ByteArray, psigs: Array): ByteArray - public fun frostSharesGen(vssCommitment: Array, pok64: ByteArray, seed32: ByteArray, totalSigners: Int, ids33: Array): Array + public fun frostSharesGen(pok64: ByteArray, seed32: ByteArray, threshold: Int, totalSigners: Int, ids33: Array): Pair,Array> /** * * total signers is deduced from the size of the totalShares array. * threshold is deduced from the vssCommitments (all vssCommitments should have the same length... which is the threshold) */ - public fun frostShareAggregate(totalShares: Array, vssCommitments: Array>, id33: ByteArray): Pair + public fun frostShareAggregate(totalShares: Array, vssCommitments: Array>, totalShareCount: Int, threshold: Int, id33: ByteArray): Pair public fun frostShareVerify(threshold: Int, id33: ByteArray, share: ByteArray, vssCommitment: Array): Int @@ -287,7 +287,7 @@ public interface Secp256k1 { * total signers is deduced from the size of the vssCommitments array. * threshold is deduced from the vssCommitments (all vssCommitments should have the same length... which is the threshold) */ - public fun frostComputePublicShare(id33: ByteArray, vssCommitments: Array>): ByteArray + public fun frostComputePublicShare(threshold: Int, id33: ByteArray, vssCommitments: Array>, totalSignersCount: Int): ByteArray public fun frostPublicKeyTweak(pk: ByteArray): ByteArray diff --git a/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt b/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt index f57fec9..d33db56 100644 --- a/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt +++ b/src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt @@ -484,27 +484,24 @@ public object Secp256k1Native : Secp256k1 { } override fun frostSharesGen( - vssCommitment: Array, pok64: ByteArray, seed32: ByteArray, + threshold: Int, totalSigners: Int, ids33: Array - ): Array { - val threshold = vssCommitment.size + ): Pair, Array> { - TODO("Constraints not yet implemented") +// TODO("Constraints not yet implemented") memScoped { val nShares = allocArray(ids33.size) + val nVssCommitment = allocArray(threshold) - val nVssCommitment = vssCommitment.map { - allocPublicKey(it).ptr - } val nIds33s = ids33.map { toNat(it) } secp256k1_frost_shares_gen( ctx = ctx, shares = nShares, - vss_commitment = nVssCommitment.toCValues(), + vss_commitment = nVssCommitment, pok64 = toNat(pok64), seed32 = toNat(seed32), threshold = threshold.convert(), @@ -512,9 +509,11 @@ public object Secp256k1Native : Secp256k1 { ids33 = nIds33s.toCValues() ) - // TODO: return serialized nShares + return Pair( + ids33.indices.map { serializeFrostShare(nShares[it]) }.toTypedArray(), + (0 until threshold).map { serializePubkey(nVssCommitment[it]) }.toTypedArray() + ) } - } private fun MemScope.serializeFrostShare(nFrostShare: secp256k1_frost_share): ByteArray { @@ -526,11 +525,10 @@ public object Secp256k1Native : Secp256k1 { override fun frostShareAggregate( totalShares: Array, vssCommitments: Array>, + totalShareCount: Int, + threshold: Int, id33: ByteArray ): Pair { - val threshold = vssCommitments.first().size - val totalShareCount = totalShares.size - TODO("Constraints not yet implemented") memScoped { @@ -538,10 +536,14 @@ public object Secp256k1Native : Secp256k1 { val nAggPublicKey = alloc() val nTotalShares = totalShares.map { allocFrostShare(it).ptr } - val nVssCommitments = vssCommitments.map { vssCommitment -> - vssCommitment.map { - allocPublicKey(it).ptr - }.toCValues() + + val nVssCommitments = allocArray>(vssCommitments.size) + vssCommitments.forEachIndexed { index, vssCommitment -> + nVssCommitments[index] = allocArrayOf( + vssCommitment.map { bytes -> + allocPublicKey(bytes).ptr + } + ).reinterpret() } secp256k1_frost_share_agg( @@ -549,7 +551,7 @@ public object Secp256k1Native : Secp256k1 { agg_share = nAggShare.ptr, agg_pk = nAggPublicKey.ptr, shares = nTotalShares.toCValues(), - vss_commitments = nVssCommitments.toTypedArray(), + vss_commitments = nVssCommitments, n_shares = totalShareCount.convert(), threshold = threshold.convert(), id33 = toNat(id33) @@ -572,38 +574,47 @@ public object Secp256k1Native : Secp256k1 { TODO("Constraints not yet implemented") memScoped { - val nId33 = toNat(id33); val nFrostShare = allocFrostShare(share) - val nPubkeys = vssCommitment.map { allocPublicKey(it).ptr } + val nVssCommitment = vssCommitment.map { allocPublicKey(it).ptr } return secp256k1_frost_share_verify( ctx = ctx, threshold = threshold.convert(), id33 = nId33, share = nFrostShare.ptr, - vss_commitment = nPubkeys.toCValues() + vss_commitment = nVssCommitment.toCValues() ) } } - override fun frostComputePublicShare(id33: ByteArray, vssCommitments: Array>): ByteArray { + override fun frostComputePublicShare( + threshold: Int, + id33: ByteArray, + vssCommitments: Array>, + totalSignersCount: Int + ): ByteArray { - TODO("Constraints not yet implemented") +// TODO("Constraints not yet implemented") memScoped { val nPubshare = alloc() - val totalSigners = vssCommitments.size - val threshold = vssCommitments.first().size - val nVssCommitments = vssCommitments.map { vssCommitment -> - vssCommitment.map { allocPublicKey(it).ptr } + + val nVssCommitments = allocArray>(vssCommitments.size) + vssCommitments.forEachIndexed { index, vssCommitment -> + nVssCommitments[index] = allocArrayOf( + vssCommitment.map { bytes -> + allocPublicKey(bytes).ptr + } + ).reinterpret() } + secp256k1_frost_compute_pubshare( ctx = ctx, pubshare = nPubshare.ptr, threshold = threshold.convert(), id33 = toNat(id33), vss_commitments = nVssCommitments, - n_participants = totalSigners.convert() + n_participants = totalSignersCount.convert() ) return serializePubkey(nPubshare)