Handle inputs/outputs and nulls correctly.

This commit is contained in:
kngako 2024-08-07 02:48:25 +02:00
parent 23739e13a8
commit 86d7d9835f
6 changed files with 123 additions and 62 deletions

View File

@ -270,10 +270,10 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
/*
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
* Method: secp256k1_frost_shares_gen
* Signature: (J[B[BII[[B)[[[B
* Signature: (J[BII[[B)[[[B
*/
JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1shares_1gen
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jint, jint, jobjectArray);
(JNIEnv *, jclass, jlong, jbyteArray, jint, jint, jobjectArray);
/*
* Class: fr_acinq_secp256k1_Secp256k1CFunctions

View File

@ -1340,11 +1340,47 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
/*
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
* Method: secp256k1_frost_share_verify
* Signature: (J[B[B[[B)I
* Method: secp256k1_frost_shares_gen
* Signature: (J[B[BII[[B)[[[B
*/
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1share_1verify
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jobjectArray)
JNIEXPORT jobjectArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1frost_1shares_1gen(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseed32, jint jthreshold, jint n_participants, jobjectArray jids33)
{
return 0;
secp256k1_context *ctx = (secp256k1_context *)jctx;
// This is what gets returned
secp256k1_frost_share shares[n_participants];
secp256k1_pubkey vss_commitment[n_participants];
unsigned char pok64[64];
// This is what gets passed
unsigned char seed32[32];
const unsigned char *ids[n_participants];
int result = 0;
result = secp256k1_frost_shares_gen(
ctx,
shares,
vss_commitment,
jpok64,
jseed32,
jthreshold,
n_participants,
jids33
);
CHECKRESULT(!result, "secp256k1_frost_shares_gen failed");
jobjectArray output = (*penv)->NewObjectArray(penv, 3, jbyteArray, NULL);
jnonce = (*penv)->NewByteArray(penv, sizeof(shares));
nonce_ptr = (*penv)->GetByteArrayElements(penv, jnonce, 0);
memcpy(nonce_ptr, nonce, sizeof(nonce));
(*penv)->ReleaseByteArrayElements(penv, jnonce, nonce_ptr, 0);
output[0];
output[1];
output[2];
return output;
}

View File

@ -264,9 +264,10 @@ public class Secp256k1CFunctions {
* this function returns 0. For uniformly random 32-byte arrays the
* chance of being invalid is negligible (around 1 in 2^128).
*
* @return output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0. If you
* do not need it, this arg can be NULL.
* @return
* [0] output_pubkey: pointer to a public key to store the result. Will be set to an invalid value if this
* function returns 0. If you do not need it, this arg can be NULL.
* [1] tweak_cache: pointer to a `frost_tweak_cache` struct initialized by `frost_pubkey_tweak`
*/
public static native byte[][] secp256k1_frost_pubkey_xonly_tweak_add(long ctx, byte[] tweakCache, byte[] tweak32);
@ -348,7 +349,7 @@ public class Secp256k1CFunctions {
* @param tweak_cache pointer to frost_tweak_cache struct (can be NULL)
*
* @return
* pointer to struct to store the partial signature
* partial_sig: pointer to struct to store the partial signature
* TODO: [1] secnonce: pointer to the secnonce struct created in frost_nonce_gen that has been never used in a
* partial_sign call before
*
@ -377,6 +378,7 @@ public class Secp256k1CFunctions {
* `secp256k1_frost_compute_pubshare`
* @param session pointer to the session that was created with `frost_nonce_process`
* @param tweakCache pointer to frost_tweak_cache struct (can be NULL)
*
* @return 0 if the arguments are invalid or the partial signature does not verify, 1 otherwise
*/
public static native int secp256k1_frost_partial_sig_verify(long ctx, byte[] partialSig, byte[] publicNonce, byte[] publicShare, byte[] session, byte[] tweakCache);

View File

@ -130,24 +130,23 @@ public object NativeSecp256k1 : Secp256k1 {
}
override fun frostSharesGen(
pok64: ByteArray,
seed32: ByteArray,
threshold: Int,
totalSigners: Int,
ids33: Array<ByteArray>
): Pair<Array<ByteArray>, Array<ByteArray>> {
): Triple<Array<ByteArray>, Array<ByteArray>, ByteArray> {
val result = Secp256k1CFunctions.secp256k1_frost_shares_gen(
Secp256k1Context.getContext(),
pok64,
seed32,
threshold,
totalSigners,
ids33
)
return Pair(
return Triple(
result[0],
result[1]
result[1],
result[2].first() // This is bad code...
)
}
@ -217,7 +216,7 @@ public object NativeSecp256k1 : Secp256k1 {
)
}
override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair<ByteArray, ByteArray> {
override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair<ByteArray?, ByteArray> {
val result = Secp256k1CFunctions.secp256k1_frost_pubkey_xonly_tweak_add(
Secp256k1Context.getContext(),
tweakCache,
@ -232,9 +231,9 @@ public object NativeSecp256k1 : Secp256k1 {
override fun frostNonceGen(
sessionId32: ByteArray,
share: ByteArray,
msg32: ByteArray,
publicKey: ByteArray,
share: ByteArray?,
msg32: ByteArray?,
publicKey: ByteArray?,
extraInput32: ByteArray?
): Pair<ByteArray, ByteArray> {
val result = Secp256k1CFunctions.secp256k1_frost_nonce_gen(
@ -258,7 +257,7 @@ public object NativeSecp256k1 : Secp256k1 {
publicKey: ByteArray,
id33: ByteArray,
ids33: Array<ByteArray>,
tweakCache: ByteArray,
tweakCache: ByteArray?,
adaptor: ByteArray?
): ByteArray {
return Secp256k1CFunctions.secp256k1_frost_nonce_process(
@ -277,7 +276,7 @@ public object NativeSecp256k1 : Secp256k1 {
secnonce: ByteArray,
share: ByteArray,
session: ByteArray,
tweakCache: ByteArray
tweakCache: ByteArray?
): ByteArray {
return Secp256k1CFunctions.secp256k1_frost_partial_sign(
Secp256k1Context.getContext(),
@ -293,7 +292,7 @@ public object NativeSecp256k1 : Secp256k1 {
publicNonce: ByteArray,
publicShare: ByteArray,
session: ByteArray,
tweakCache: ByteArray
tweakCache: ByteArray?
): Int {
return Secp256k1CFunctions.secp256k1_frost_partial_sig_verify(
Secp256k1Context.getContext(),

View File

@ -271,7 +271,7 @@ public interface Secp256k1 {
*/
public fun musigPartialSigAgg(session: ByteArray, psigs: Array<ByteArray>): ByteArray
public fun frostSharesGen(pok64: ByteArray, seed32: ByteArray, threshold: Int, totalSigners: Int, ids33: Array<ByteArray>): Pair<Array<ByteArray>,Array<ByteArray>>
public fun frostSharesGen(seed32: ByteArray, threshold: Int, totalSigners: Int, ids33: Array<ByteArray>): Triple<Array<ByteArray>,Array<ByteArray>, ByteArray>
/**
*
@ -291,21 +291,21 @@ public interface Secp256k1 {
public fun frostPublicKeyTweak(xOnlyPublicKey: ByteArray): ByteArray
public fun frostPublicKeyEcTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): ByteArray
public fun frostPublicKeyEcTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): ByteArray?
public fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair<ByteArray, ByteArray>
public fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair<ByteArray?, ByteArray>
public fun frostNonceGen(sessionId32: ByteArray, share: ByteArray, msg32: ByteArray, publicKey: ByteArray, extraInput32: ByteArray?): Pair<ByteArray, ByteArray>
public fun frostNonceGen(sessionId32: ByteArray, share: ByteArray?, msg32: ByteArray?, publicKey: ByteArray?, extraInput32: ByteArray?): Pair<ByteArray, ByteArray>
/**
*
* threshold can be deduced from the size of the pubnonces array.
*/
public fun frostNonceProcess(publicNonces: Array<ByteArray>, msg32: ByteArray, publicKey: ByteArray, id33: ByteArray, ids33: Array<ByteArray>, tweakCache: ByteArray, adaptor: ByteArray?): ByteArray
public fun frostNonceProcess(publicNonces: Array<ByteArray>, msg32: ByteArray, publicKey: ByteArray, id33: ByteArray, ids33: Array<ByteArray>, tweakCache: ByteArray?, adaptor: ByteArray?): ByteArray
public fun frostPartialSign(secnonce: ByteArray, share: ByteArray, session: ByteArray, tweakCache: ByteArray): ByteArray
public fun frostPartialSign(secnonce: ByteArray, share: ByteArray, session: ByteArray, tweakCache: ByteArray?): ByteArray
public fun frostPartialSignatureVerify(partialSig: ByteArray, publicNonce: ByteArray, publicShare: ByteArray, session: ByteArray, tweakCache: ByteArray): Int
public fun frostPartialSignatureVerify(partialSig: ByteArray, publicNonce: ByteArray, publicShare: ByteArray, session: ByteArray, tweakCache: ByteArray?): Int
public fun frostPartialSignatureAggregate(session: ByteArray, partialSignatures: Array<ByteArray>): ByteArray

View File

@ -484,13 +484,11 @@ public object Secp256k1Native : Secp256k1 {
}
override fun frostSharesGen(
pok64: ByteArray,
seed32: ByteArray,
threshold: Int,
totalSigners: Int,
ids33: Array<ByteArray>
): Pair<Array<ByteArray>, Array<ByteArray>> {
require(pok64.size == 64)
): Triple<Array<ByteArray>, Array<ByteArray>, ByteArray> {
require(seed32.size == 32)
require(threshold > 0)
require(threshold <= totalSigners)
@ -500,6 +498,7 @@ public object Secp256k1Native : Secp256k1 {
memScoped {
val nShares = allocArray<secp256k1_frost_share>(ids33.size)
val nVssCommitment = allocArray<secp256k1_pubkey>(threshold)
val pok64 = ByteArray(64)
val nIds33s = ids33.map { toNat(it) }
@ -514,9 +513,10 @@ public object Secp256k1Native : Secp256k1 {
ids33 = nIds33s.toCValues()
)
return Pair(
return Triple(
ids33.indices.map { serializeFrostShare(nShares[it]) }.toTypedArray(),
(0 until threshold).map { serializePubkey(nVssCommitment[it]) }.toTypedArray()
(0 until threshold).map { serializePubkey(nVssCommitment[it]) }.toTypedArray(),
pok64
)
}
}
@ -696,7 +696,7 @@ public object Secp256k1Native : Secp256k1 {
return natOutput
}
override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair<ByteArray, ByteArray> {
override fun frostPublicKeyXonlyTweakAdd(tweakCache: ByteArray, tweak32: ByteArray): Pair<ByteArray?, ByteArray> {
require(tweakCache.size == Secp256k1.FROST_TWEAK_CACHE_SIZE)
require(tweak32.size == 32)
@ -735,15 +735,21 @@ public object Secp256k1Native : Secp256k1 {
override fun frostNonceGen(
sessionId32: ByteArray,
share: ByteArray,
msg32: ByteArray,
publicKey: ByteArray,
share: ByteArray?,
msg32: ByteArray?,
publicKey: ByteArray?,
extraInput32: ByteArray?
): Pair<ByteArray, ByteArray> {
require(sessionId32.size == 32)
share?.let {
require(share.size == Secp256k1.FROST_SHARE_SIZE)
}
msg32?.let {
require(msg32.size == 33)
}
publicKey?.let {
require(publicKey.size == 33 || publicKey.size == 65)
}
extraInput32?.let {
require(it.size == 33)
}
@ -752,8 +758,8 @@ public object Secp256k1Native : Secp256k1 {
val nFrostSecnonce = alloc<secp256k1_frost_secnonce>()
val nPublicNonce = alloc<secp256k1_frost_pubnonce>()
val nShare = allocFrostShare(share)
val nPublicKey = allocXonlyPublicKey(publicKey)
val nShare = share?.let { allocFrostShare(it) }
val nPublicKey = publicKey?.let { allocXonlyPublicKey(it) }
val nExtraInput32 = extraInput32?.let {
toNat(it)
}
@ -763,9 +769,9 @@ public object Secp256k1Native : Secp256k1 {
secnonce = nFrostSecnonce.ptr,
pubnonce = nPublicNonce.ptr,
session_id32 = toNat(sessionId32),
agg_share = nShare.ptr,
msg32 = toNat(msg32),
agg_pk = nPublicKey.ptr,
agg_share = nShare?.ptr,
msg32 = msg32?.let { toNat(it) },
agg_pk = nPublicKey?.ptr,
extra_input32 = nExtraInput32
)
@ -788,7 +794,7 @@ public object Secp256k1Native : Secp256k1 {
publicKey: ByteArray,
id33: ByteArray,
ids33: Array<ByteArray>,
tweakCache: ByteArray,
tweakCache: ByteArray?,
adaptor: ByteArray?
): ByteArray {
publicNonces.forEach { publicNonce ->
@ -799,7 +805,9 @@ public object Secp256k1Native : Secp256k1 {
ids33.forEach {
require(it.size == 33)
}
tweakCache?.let {
require(tweakCache.size == Secp256k1.FROST_TWEAK_CACHE_SIZE)
}
adaptor?.let {
require(it.size == 33 || it.size == 65)
}
@ -813,8 +821,11 @@ public object Secp256k1Native : Secp256k1 {
val nIds33 = ids33.map { toNat(it) }
val nTweakCache = alloc<secp256k1_frost_tweak_cache>()
val nTweakCache = tweakCache?.let {
alloc<secp256k1_frost_tweak_cache>()
}?.also { nTweakCache ->
memcpy(nTweakCache.ptr, toNat(tweakCache) , Secp256k1.FROST_TWEAK_CACHE_SIZE.toULong())
}
val nAdaptor = adaptor?.let {
allocPublicKey(it).ptr
@ -828,7 +839,7 @@ public object Secp256k1Native : Secp256k1 {
agg_pk = nPublicKey.ptr,
my_id33 = toNat(id33),
ids33 = nIds33.toCValues(),
tweak_cache = nTweakCache.ptr,
tweak_cache = nTweakCache?.ptr,
adaptor = nAdaptor
)
@ -850,12 +861,15 @@ public object Secp256k1Native : Secp256k1 {
secnonce: ByteArray,
share: ByteArray,
session: ByteArray,
tweakCache: ByteArray
tweakCache: ByteArray?
): ByteArray {
require(secnonce.size == Secp256k1.FROST_SECNONCE_SIZE)
require(share.size == Secp256k1.FROST_SHARE_SIZE)
require(session.size == Secp256k1.FROST_SESSION_SIZE)
tweakCache?.let {
require(tweakCache.size == Secp256k1.FROST_TWEAK_CACHE_SIZE)
}
memScoped {
val nPartialSignature = alloc<secp256k1_frost_partial_sig>();
@ -868,8 +882,12 @@ public object Secp256k1Native : Secp256k1 {
val nSession = alloc<secp256k1_frost_session>()
memcpy(nSession.ptr, toNat(session), Secp256k1.FROST_SESSION_SIZE.toULong())
val nTweakCache = alloc<secp256k1_frost_tweak_cache>()
val nTweakCache = tweakCache?.let {
alloc<secp256k1_frost_tweak_cache>()
}?.also { nTweakCache ->
memcpy(nTweakCache.ptr, toNat(tweakCache) , Secp256k1.FROST_TWEAK_CACHE_SIZE.toULong())
}
secp256k1_frost_partial_sign(
ctx,
@ -877,7 +895,7 @@ public object Secp256k1Native : Secp256k1 {
nSecnonce.ptr,
nShare.ptr,
nSession.ptr,
nTweakCache.ptr
nTweakCache?.ptr
)
return serializeFrostPartialSignature(nPartialSignature)
@ -889,13 +907,16 @@ public object Secp256k1Native : Secp256k1 {
publicNonce: ByteArray,
publicShare: ByteArray,
session: ByteArray,
tweakCache: ByteArray
tweakCache: ByteArray?
): Int {
require(partialSig.size == 32)
require(publicNonce.size == Secp256k1.MUSIG2_PUBLIC_NONCE_SIZE)
require(publicShare.size == 33 || publicShare.size == 65)
require(session.size == Secp256k1.FROST_SESSION_SIZE)
tweakCache?.let {
require(tweakCache.size == Secp256k1.FROST_TWEAK_CACHE_SIZE)
}
memScoped {
val nPartialSignature = allocFrostPartialSignature(partialSig)
@ -903,8 +924,11 @@ public object Secp256k1Native : Secp256k1 {
val nPublicShare = allocPublicKey(publicShare)
val nSession = alloc<secp256k1_frost_session>()
memcpy(nSession.ptr, toNat(session), Secp256k1.FROST_SESSION_SIZE.toULong())
val nTweakCache = alloc<secp256k1_frost_tweak_cache>()
val nTweakCache = tweakCache?.let {
alloc<secp256k1_frost_tweak_cache>()
}?.also { nTweakCache ->
memcpy(nTweakCache.ptr, toNat(tweakCache) , Secp256k1.FROST_TWEAK_CACHE_SIZE.toULong())
}
return secp256k1_frost_partial_sig_verify(
ctx,
@ -912,7 +936,7 @@ public object Secp256k1Native : Secp256k1 {
nPublicNonce.ptr,
nPublicShare.ptr,
nSession.ptr,
nTweakCache.ptr
nTweakCache?.ptr
)
}
}