Getting started with unit tests

This commit is contained in:
kngako 2024-08-18 01:27:04 +02:00
parent 32ee077995
commit e7f074d36e
6 changed files with 263 additions and 24 deletions

View File

@ -1359,8 +1359,8 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2
{
secp256k1_context *ctx = (secp256k1_context *)jctx;
secp256k1_frost_share *shares;
secp256k1_pubkey* vss_commitment;
secp256k1_frost_share **shares;
secp256k1_pubkey **vss_commitment;
jbyte* pok64;
size_t size;
@ -1420,11 +1420,37 @@ JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp2
jobjectArray output = (*penv)->NewObjectArray(penv, 2, jobjectArray, NULL);
output[0] = (*penv)->NewObjectArray(penv, jn_participants, jbyteArray, NULL);
jobjectArray jshares = (*penv)->NewObjectArray(penv, jn_participants, jbyteArray, NULL);
// Copy shares into jshares
unsigned char out32[32];
for (i = 0; i < jn_participants; i++)
{
result = secp256k1_frost_share_serialize(ctx, out32, shares[i]);
CHECKRESULT(!result, "secp256k1_frost_share_serialize failed");
output[1] = (*penv)->NewObjectArray(penv, jthreshold, jbyteArray, NULL);
jbyteArray jshare = (*penv)->NewByteArray(penv, 32);
copy_bytes_to_java(penv, jshare, 32, out32);
jshares[i] = jshare;
}
output[0] = jshares;
jobjectArray jvss_commitment = (*penv)->NewObjectArray(penv, jthreshold, jbyteArray, NULL);
// Copy vss_commitment into jvss_commitment
for (i = 0; i < jn_participants; i++)
{
// need share object...
result = secp256k1_xonly_pubkey_serialize(ctx, out32, vss_commitment[i]);
CHECKRESULT(!result, "secp256k1_xonly_pubkey_serialize failed");
jbyteArray jpubkey = (*penv)->NewByteArray(penv, 32);
copy_bytes_to_java(penv, jpubkey, 32, out32);
jvss_commitment[i] = jpubkey;
}
output[1] = jvss_commitment;
// TODO: Copy over the required data...
return output;
}

View File

@ -489,11 +489,11 @@ public object Secp256k1Native : Secp256k1 {
totalSigners: Int,
ids33: Array<ByteArray>
): Triple<Array<ByteArray>, Array<ByteArray>, ByteArray> {
require(seed32.size == 32)
require(threshold > 0)
require(threshold <= totalSigners)
require(ids33.size == totalSigners)
ids33.forEach { require(it.size == 33) }
require(seed32.size == 32, { "seed size should be 32" })
require(threshold > 1, { "threshold cannot be less then 1" })
require(threshold <= totalSigners, { "threshold($threshold) cannot be greater then totalSigners ($totalSigners)" })
require(ids33.size == totalSigners, { "ids33 size need to be the same as totalSigners size" })
ids33.forEach { require(it.size == 33, { "id33 size must be 33" }) }
memScoped {
val nShares = allocArray<secp256k1_frost_share>(ids33.size)
@ -543,7 +543,7 @@ public object Secp256k1Native : Secp256k1 {
require(publicKey.size == 33 || publicKey.size == 65)
}
}
require(threshold > 0)
require(threshold > 1)
require(threshold <= totalShareCount)
require(id33.size == 33)
@ -587,7 +587,7 @@ public object Secp256k1Native : Secp256k1 {
share: ByteArray,
vssCommitment: Array<ByteArray>
): Int {
require(threshold > 0)
require(threshold > 1)
require(id33.size == 33)
require(share.size == Secp256k1.FROST_SHARE_SIZE)
@ -617,7 +617,7 @@ public object Secp256k1Native : Secp256k1 {
vssCommitments: Array<Array<ByteArray>>,
totalSignersCount: Int
): ByteArray {
require(threshold > 0)
require(threshold > 1)
require(threshold <= totalSignersCount)
require(id33.size == 33)

View File

@ -0,0 +1,24 @@
package fr.acinq.secp256k1
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import org.kodein.memory.file.FileSystem
import org.kodein.memory.file.Path
import org.kodein.memory.file.openReadableFile
import org.kodein.memory.file.resolve
import org.kodein.memory.system.Environment
import org.kodein.memory.text.readString
import org.kodein.memory.use
abstract class BaseTest {
fun resourcesDir() =
Environment.findVariable("TEST_RESOURCES_PATH")?.let { Path(it) }
?: FileSystem.workingDir().resolve("src/commonTest/resources")
fun readData(filename: String): JsonElement {
val file = resourcesDir().resolve(filename)
val raw = file.openReadableFile().use { it.readString() }
val format = Json { ignoreUnknownKeys = true }
return format.parseToJsonElement(raw)
}
}

View File

@ -0,0 +1,115 @@
package fr.acinq.secp256k1
import kotlinx.serialization.json.*
import kotlin.test.*
class FrostTest: BaseTest() {
// Frost Share Generation
@Test
fun `frost share generation`() {
val tests = readData("frost/share_gen_vectors.json")
val pubkeys = tests.jsonObject["pubkeys"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) }
tests.jsonObject["valid_test_cases"]!!.jsonArray.forEach { validTestCases ->
val keyIndices = validTestCases.jsonObject["key_indices"]!!.jsonArray.map { it.jsonPrimitive.int }
val seed32 = ByteArray(32)
val nParticipants = keyIndices.size
val threshold = validTestCases.jsonObject["threshold"]!!.jsonPrimitive.int
val ids33 = keyIndices.map { pubkeys[it] }.toTypedArray()
val result = Secp256k1.frostSharesGen(
seed32,
threshold,
nParticipants,
ids33
)
val expected = validTestCases.jsonObject["expected"]!!;
val expectedShare = expected.jsonObject["frost_share"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) }
val expectedVSSCommitment = expected.jsonObject["vss_commitment"]!!.jsonArray.map { Hex.decode(it.jsonPrimitive.content) }
val expectedPoK64 = Hex.decode(expected.jsonObject["pok64"]!!.jsonPrimitive.content)
result.first.forEachIndexed { index, share ->
assertEquals(
expected = Hex.encode(expectedShare[index]),
actual = Hex.encode(share),
"Unexpected $index:share for $keyIndices test case"
)
}
result.second.forEachIndexed { index, vssCommitment ->
assertEquals(
expected = Hex.encode(expectedVSSCommitment[index]),
actual = Hex.encode(vssCommitment),
"Unexpected $index:vss_commitment for the $keyIndices test case"
)
}
assertEquals(
expected = Hex.encode(expectedPoK64),
actual = Hex.encode(result.third),
message = "Unexpected pok64 for $keyIndices test case"
)
}
}
@Test
fun `frost share aggregation`() {
}
@Test
fun `frost share verify`() {
}
@Test
fun `frost compute pubshare`() {
}
// Frost Tweak
@Test
fun `frost pubkey tweak`() {
}
@Test
fun `frost pubkey ec tweak add`() {
}
@Test
fun `frost pubkey xonly tweak add`() {
}
// Frost Sign functionality
@Test
fun `frost nonce gen`() {
}
@Test
fun `frost nonce process`() {
}
@Test
fun `frost partial sign `() {
}
@Test
fun `frost partial signature verify`() {
}
@Test
fun `frost partial signature aggregation`() {
}
}

View File

@ -10,17 +10,7 @@ import org.kodein.memory.text.readString
import org.kodein.memory.use
import kotlin.test.*
class Musig2Test {
fun resourcesDir() =
Environment.findVariable("TEST_RESOURCES_PATH")?.let { Path(it) }
?: FileSystem.workingDir().resolve("src/commonTest/resources")
fun readData(filename: String): JsonElement {
val file = resourcesDir().resolve(filename)
val raw = file.openReadableFile().use { it.readString() }
val format = Json { ignoreUnknownKeys = true }
return format.parseToJsonElement(raw)
}
class Musig2Test: BaseTest() {
@Test
fun `aggregate public keys`() {

View File

@ -0,0 +1,84 @@
{
"pubkeys": [
"02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
"03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
"023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66",
"04F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
"03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9",
"020000000000000000000000000000000000000000000000000000000000000005",
"02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30"
],
"valid_test_cases": [
{
"key_indices": [0, 1, 2, 3, 4],
"threshold": 3,
"expected": {
"frost_share": [
"0d9c85106ab6168b13e3b569695fb57bf91cbbe1e589a205b48bb7e15ff6908b",
"807eb5b22ef56d6ae3601f2774a1985485386f6317e6bc075b2134818fd44c5b",
"5e67fe075e91549bf28558a0d55e4b954bf5f9f229ddc0d6e9ab76a139367bbf",
"d248680a6aa524a75c9f59c2732e77ac2d334b98ac2b09defc9030da218d17ca",
"7bdf748e9fd56cd87e0430847e3212d0814528aeb83e1d83aeda279cbc20b481"
],
"vss_commitment": [
"044c865c8c3f29a10a55bee4deca73b135d768eb7727a7ccc0fd47db82d7c9f4763d0ebe8feabf6b2119098f1f1f52ba165ae373d75a73c053f4bff6bd2ddb361f",
"045500faa3f2c4279bb95e66bd4c0011da084806e260395c0ff02ae25bd80102f45a7b7fe4d90cc76e9b26a1f9a9febcd0c767aeee63ab463fcfe559ac3b3ad653",
"0499c4d8f4ed163d07a112a74c0b03e1f6851b86b499b916d66824cec9694e5bd866e108b3f82413bdf96c6abde9995a165684432467b82be13dd73e67e4cf29f9"
],
"pok64": "e79e0d894639155ffebbe03e97030758e6060929a468010ce70627b1ce92b553597f1709f2d82a2ad884f868123344ec871eec4cbf1fa12c5794df6fe5d06e27"
}
},
{
"key_indices": [4, 3, 2, 1, 0],
"threshold": 3,
"expected": {
"frost_share": [
"bdf8c4896736812a5548610bd39b66dc91b266e1bc68db4e760bcee797a695e3",
"5afe66c979b666141b8bf46747293797e74580341527f5f6aa01277a468fd9f2",
"9efe2e26dcf8e6f4224fea1fec9a9167ec29cb3b727f841ef76e23d592d2512f",
"dd4fd050344dc625737d018c69298ed312bd7043d3343583625703ed45726ac6",
"eb486a1c2e3ff755473fc41b01138b6a0d3f99f3b99b420e57271689d40eb7e4"
],
"vss_commitment": [
"0496291d2a1ec0f0e38d622db473004c18bd6713be47642cfdd7ad9c458a12506da5eb9d0b0a99aab0c97f5ac6d94f2becd8075eef8675d06e4b6cf9e58ed4c30b",
"0473b3681ac295de098568695b02820d57cab4c09f953518bfe1d133b54d794564da8a4c508942789b32fd483719bd847ab0a6f87e0ef7bb7d40376e1c109c0bda",
"044cd2e10e73b39450f2ce02609985ea1f2d84891a0485fbf42ddf9164c0dd5222306a396efb13eff789837b894ca6bf3681d1f937b94e209a8e8333e1e5a7d6c1"
],
"pok64": "5f4e653cd392b04042629b78bc5982c552a4027816321355e519912e1e46514b6425bd31ae684a1ce1941a98cfb0d2b9ad108a39e230b4303e0e0237d7136998"
}
},
{
"key_indices": [0, 0, 0],
"threshold": 2,
"expected": {
"frost_share": [
"2bc9a1e8064cc39759023561f07507ad72db7e7fa20b7a01ec467d40bed167ff",
"2bc9a1e8064cc39759023561f07507ad72db7e7fa20b7a01ec467d40bed167ff",
"2bc9a1e8064cc39759023561f07507ad72db7e7fa20b7a01ec467d40bed167ff"
],
"vss_commitment": [
"041857d4fce91165cba35a6a074ce182883c92eaf0e8c97d985bb73db2befcee02dbcd9ba5bb8e01878d9900738833bc5111c20996b9f5f14da50011a0a4e0767f",
"04702b5ed0a3f937ca894a976f7927f537e37e19eafcf7ed970087b860bfa80f7c64a060e1835fdfe8780abf7d0dbb11b4334471aa133f1fa159c0151faf16edee"
],
"pok64": "2081623ec3b670010d6a8ce55073cf0ef9906798b18db58b1385211d6a7b206e2408e5fc9c399fd1a448686cd29aa71e6053229bf42c5710a5f10af0af1140b0"
}
},
{
"key_indices": [0, 0, 1, 1],
"threshold": 2,
"expected": {
"frost_share": [
"70656f19f741cb3e1a46d033321c1627e4464f08316f0d2faad738903b2b2df9",
"70656f19f741cb3e1a46d033321c1627e4464f08316f0d2faad738903b2b2df9",
"624956ad9497abe08d08e4e367519b0c263d79d14754c4a6fb7b2b67796c3636",
"624956ad9497abe08d08e4e367519b0c263d79d14754c4a6fb7b2b67796c3636"
],
"vss_commitment": [
"04267d0994c34e87b281506e325a64b83935acb172e5d51a451b5e5f21f51490489dd865654935008aa6afb48955259ace1f8a7eeeafb95c2b0d78dec8e5f25361",
"04c616024ec0c9317bd7574b4fb55a9202d2e6d53465bfb37d1f9edcffc775df537c7c521eac64316f1339943c219df37fa597a49d6be6a2487d776b8305c3880c"
],
"pok64": "ea25763debd2b96d9e24a3cf3d87f792bce88a27787c0b84bc0b2fc5a1fec841afc6606bc970e477694b1f3c6ad25370c06a7b9705d52c3acfec13b036a94df8"
}
}
]
}