Use local secp256k1 callbacks in kotlin native code

This commit is contained in:
sstone 2023-12-12 12:08:13 +01:00
parent aadffabe42
commit 0364ec762e
No known key found for this signature in database
GPG Key ID: 7A73FE77DE2C4027
3 changed files with 185 additions and 144 deletions

View File

@ -36,15 +36,6 @@ void JNI_ThrowByName(JNIEnv *penv, const char *name, const char *msg)
secp256k1_context_set_error_callback(ctx, my_error_callback_fn, &error_callback_message); \ secp256k1_context_set_error_callback(ctx, my_error_callback_fn, &error_callback_message); \
secp256k1_context_set_illegal_callback(ctx, my_illegal_callback_fn, &illegal_callback_message); secp256k1_context_set_illegal_callback(ctx, my_illegal_callback_fn, &illegal_callback_message);
#define CHECKRESULT(errorcheck, message) \
{ \
if (errorcheck) \
{ \
JNI_ThrowByName(penv, "fr/acinq/secp256k1/Secp256k1Exception", message); \
return 0; \
} \
}
#define CHECKRESULT(errorcheck, message) \ #define CHECKRESULT(errorcheck, message) \
{ \ { \
if (error_callback_message) \ if (error_callback_message) \
@ -727,7 +718,9 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
SETUP_ERROR_CALLBACKS SETUP_ERROR_CALLBACKS
// we do not check that recid is valid, which should trigger our illegal callback handler to throw a Secp256k1IllegalCallbackException
// CHECKRESULT(recid < 0 || recid > 3, "recid must be 0, 1, 2 or 3") // CHECKRESULT(recid < 0 || recid > 3, "recid must be 0, 1, 2 or 3")
sigSize = (*penv)->GetArrayLength(penv, jsig); sigSize = (*penv)->GetArrayLength(penv, jsig);
int sigFormat = GetSignatureFormat(sigSize); int sigFormat = GetSignatureFormat(sigSize);
CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size"); CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size");
@ -774,7 +767,6 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
secp256k1_context *ctx = (secp256k1_context *)jctx; secp256k1_context *ctx = (secp256k1_context *)jctx;
jbyte *sig; jbyte *sig;
secp256k1_ecdsa_signature signature; secp256k1_ecdsa_signature signature;
;
unsigned char der[73]; unsigned char der[73];
size_t size; size_t size;
int result = 0; int result = 0;

View File

@ -4,62 +4,65 @@ import kotlinx.cinterop.*
import platform.posix.size_tVar import platform.posix.size_tVar
import secp256k1.* import secp256k1.*
private typealias MyHandler = (String) -> Unit private typealias Secp256k1CallbackHandler = (String) -> Unit
private object CallbackHandler { @OptIn(ExperimentalStdlibApi::class)
private class CallbackHandler(ctx: CPointer<secp256k1_context>) : AutoCloseable {
var illegalCallBackMessage: String? = null var illegalCallBackMessage: String? = null
val illegalHandler: MyHandler = { x: String -> illegalCallBackMessage = x } val illegalHandler: Secp256k1CallbackHandler = { x: String -> illegalCallBackMessage = x }
val illegalCallbackRef = StableRef.create(illegalHandler) val illegalCallbackRef = StableRef.create(illegalHandler)
var errorCallBackMessage: String? = null var errorCallBackMessage: String? = null
val errorHandler: MyHandler = { x: String -> errorCallBackMessage = x } val errorHandler: Secp256k1CallbackHandler = { x: String -> errorCallBackMessage = x }
val errorCallbackRef = StableRef.create(errorHandler) val errorCallbackRef = StableRef.create(errorHandler)
fun checkForErrors() { init {
if (errorCallBackMessage != null) {
val message = errorCallBackMessage
errorCallBackMessage = null
throw Secp256k1ErrorCallbackException(message)
}
if (illegalCallBackMessage != null) {
val message = illegalCallBackMessage
illegalCallBackMessage = null
throw Secp256k1IllegalCallbackException(message)
}
}
}
@OptIn(ExperimentalUnsignedTypes::class)
public object Secp256k1Native : Secp256k1 {
private val ctx: CPointer<secp256k1_context> by lazy {
val ctx = secp256k1_context_create((SECP256K1_FLAGS_TYPE_CONTEXT or SECP256K1_FLAGS_BIT_CONTEXT_SIGN or SECP256K1_FLAGS_BIT_CONTEXT_VERIFY).toUInt())
?: error("Could not create secp256k1 context")
secp256k1_context_set_error_callback( secp256k1_context_set_error_callback(
ctx, staticCFunction { buffer: CPointer<ByteVar>?, data: COpaquePointer? -> ctx, staticCFunction { buffer: CPointer<ByteVar>?, data: COpaquePointer? ->
if (data != null) { if (data != null) {
val callback = data.asStableRef<MyHandler>().get() val callback = data.asStableRef<Secp256k1CallbackHandler>().get()
callback(buffer?.toKString() ?: "error callback triggered") callback(buffer?.toKString() ?: "error callback triggered")
} }
}, },
CallbackHandler.errorCallbackRef.asCPointer() errorCallbackRef.asCPointer()
) )
secp256k1_context_set_illegal_callback( secp256k1_context_set_illegal_callback(
ctx, staticCFunction { buffer: CPointer<ByteVar>?, data: COpaquePointer? -> ctx, staticCFunction { buffer: CPointer<ByteVar>?, data: COpaquePointer? ->
if (data != null) { if (data != null) {
val callback = data.asStableRef<MyHandler>().get() val callback = data.asStableRef<Secp256k1CallbackHandler>().get()
callback(buffer?.toKString() ?: "illegal callback triggered") callback(buffer?.toKString() ?: "illegal callback triggered")
} }
}, },
CallbackHandler.illegalCallbackRef.asCPointer() illegalCallbackRef.asCPointer()
) )
}
ctx fun checkForErrors() {
errorCallBackMessage?.let { throw Secp256k1ErrorCallbackException(it) }
illegalCallBackMessage?.let { throw Secp256k1IllegalCallbackException(it) }
}
override fun close() {
// StableRef instances have to be disposed of manually
illegalCallbackRef.dispose()
errorCallbackRef.dispose()
}
}
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalStdlibApi::class)
public object Secp256k1Native : Secp256k1 {
private val ctx: CPointer<secp256k1_context> by lazy {
secp256k1_context_create((SECP256K1_FLAGS_TYPE_CONTEXT or SECP256K1_FLAGS_BIT_CONTEXT_SIGN or SECP256K1_FLAGS_BIT_CONTEXT_VERIFY).toUInt())
?: error("Could not create secp256k1 context")
} }
private fun Int.requireSuccess(message: String): Int { private fun Int.requireSuccess(message: String): Int {
CallbackHandler.checkForErrors() return if (this != 1) throw Secp256k1Exception(message) else this
}
private fun Int.requireSuccess(callbackHandler: CallbackHandler, message: String): Int {
callbackHandler.checkForErrors()
return if (this != 1) throw Secp256k1Exception(message) else this return if (this != 1) throw Secp256k1Exception(message) else this
} }
@ -107,168 +110,209 @@ public object Secp256k1Native : Secp256k1 {
public override fun verify(signature: ByteArray, message: ByteArray, pubkey: ByteArray): Boolean { public override fun verify(signature: ByteArray, message: ByteArray, pubkey: ByteArray): Boolean {
require(message.size == 32) require(message.size == 32)
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPubkey = allocPublicKey(pubkey) memScoped {
val nMessage = toNat(message) val nPubkey = allocPublicKey(pubkey)
val nSig = allocSignature(signature) val nMessage = toNat(message)
return secp256k1_ecdsa_verify(ctx, nSig.ptr, nMessage, nPubkey.ptr) == 1 val nSig = allocSignature(signature)
val verify = secp256k1_ecdsa_verify(ctx, nSig.ptr, nMessage, nPubkey.ptr)
callbackHandler.checkForErrors()
return verify == 1
}
} }
} }
public override fun sign(message: ByteArray, privkey: ByteArray): ByteArray { public override fun sign(message: ByteArray, privkey: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
require(message.size == 32) require(message.size == 32)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPrivkey = toNat(privkey) memScoped {
val nMessage = toNat(message) val nPrivkey = toNat(privkey)
val nSig = alloc<secp256k1_ecdsa_signature>() val nMessage = toNat(message)
secp256k1_ecdsa_sign(ctx, nSig.ptr, nMessage, nPrivkey, null, null).requireSuccess("secp256k1_ecdsa_sign() failed") val nSig = alloc<secp256k1_ecdsa_signature>()
return serializeSignature(nSig) secp256k1_ecdsa_sign(ctx, nSig.ptr, nMessage, nPrivkey, null, null).requireSuccess(callbackHandler, "secp256k1_ecdsa_sign() failed")
return serializeSignature(nSig)
}
} }
} }
public override fun signatureNormalize(sig: ByteArray): Pair<ByteArray, Boolean> { public override fun signatureNormalize(sig: ByteArray): Pair<ByteArray, Boolean> {
require(sig.size >= 64){ "invalid signature ${Hex.encode(sig)}" } require(sig.size >= 64) { "invalid signature ${Hex.encode(sig)}" }
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nSig = allocSignature(sig) memScoped {
val isHighS = secp256k1_ecdsa_signature_normalize(ctx, nSig.ptr, nSig.ptr) val nSig = allocSignature(sig)
return Pair(serializeSignature(nSig), isHighS == 1) val isHighS = secp256k1_ecdsa_signature_normalize(ctx, nSig.ptr, nSig.ptr)
callbackHandler.checkForErrors()
return Pair(serializeSignature(nSig), isHighS == 1)
}
} }
} }
public override fun secKeyVerify(privkey: ByteArray): Boolean { public override fun secKeyVerify(privkey: ByteArray): Boolean {
if (privkey.size != 32) return false if (privkey.size != 32) return false
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPrivkey = toNat(privkey) memScoped {
return secp256k1_ec_seckey_verify(ctx, nPrivkey) == 1 val nPrivkey = toNat(privkey)
val result = secp256k1_ec_seckey_verify(ctx, nPrivkey) == 1
callbackHandler.checkForErrors()
return result
}
} }
} }
public override fun pubkeyCreate(privkey: ByteArray): ByteArray { public override fun pubkeyCreate(privkey: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPrivkey = toNat(privkey) memScoped {
val nPubkey = alloc<secp256k1_pubkey>() val nPrivkey = toNat(privkey)
secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nPrivkey).requireSuccess("secp256k1_ec_pubkey_create() failed") val nPubkey = alloc<secp256k1_pubkey>()
return serializePubkey(nPubkey) secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nPrivkey).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_create() failed")
return serializePubkey(nPubkey)
}
} }
} }
public override fun pubkeyParse(pubkey: ByteArray): ByteArray { public override fun pubkeyParse(pubkey: ByteArray): ByteArray {
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPubkey = allocPublicKey(pubkey) memScoped {
return serializePubkey(nPubkey) val nPubkey = allocPublicKey(pubkey)
val result = serializePubkey(nPubkey)
callbackHandler.checkForErrors()
return result
}
} }
} }
public override fun privKeyNegate(privkey: ByteArray): ByteArray { public override fun privKeyNegate(privkey: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val negated = privkey.copyOf() memScoped {
val negPriv = toNat(negated) val negated = privkey.copyOf()
secp256k1_ec_seckey_negate(ctx, negPriv).requireSuccess("secp256k1_ec_seckey_negate() failed") val negPriv = toNat(negated)
return negated secp256k1_ec_seckey_negate(ctx, negPriv).requireSuccess(callbackHandler, "secp256k1_ec_seckey_negate() failed")
return negated
}
} }
} }
public override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray { public override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val added = privkey.copyOf() memScoped {
val natAdd = toNat(added) val added = privkey.copyOf()
val natTweak = toNat(tweak) val natAdd = toNat(added)
secp256k1_ec_seckey_tweak_add(ctx, natAdd, natTweak).requireSuccess("secp256k1_ec_seckey_tweak_add() failed") val natTweak = toNat(tweak)
return added secp256k1_ec_seckey_tweak_add(ctx, natAdd, natTweak).requireSuccess(callbackHandler, "secp256k1_ec_seckey_tweak_add() failed")
return added
}
} }
} }
public override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray { public override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val multiplied = privkey.copyOf() memScoped {
val natMul = toNat(multiplied) val multiplied = privkey.copyOf()
val natTweak = toNat(tweak) val natMul = toNat(multiplied)
secp256k1_ec_privkey_tweak_mul(ctx, natMul, natTweak).requireSuccess("secp256k1_ec_privkey_tweak_mul() failed") val natTweak = toNat(tweak)
return multiplied secp256k1_ec_privkey_tweak_mul(ctx, natMul, natTweak).requireSuccess(callbackHandler, "secp256k1_ec_privkey_tweak_mul() failed")
return multiplied
}
} }
} }
public override fun pubKeyNegate(pubkey: ByteArray): ByteArray { public override fun pubKeyNegate(pubkey: ByteArray): ByteArray {
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPubkey = allocPublicKey(pubkey) memScoped {
secp256k1_ec_pubkey_negate(ctx, nPubkey.ptr).requireSuccess("secp256k1_ec_pubkey_negate() failed") val nPubkey = allocPublicKey(pubkey)
return serializePubkey(nPubkey) secp256k1_ec_pubkey_negate(ctx, nPubkey.ptr).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_negate() failed")
return serializePubkey(nPubkey)
}
} }
} }
public override fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray { public override fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPubkey = allocPublicKey(pubkey) memScoped {
val nTweak = toNat(tweak) val nPubkey = allocPublicKey(pubkey)
secp256k1_ec_pubkey_tweak_add(ctx, nPubkey.ptr, nTweak).requireSuccess("secp256k1_ec_pubkey_tweak_add() failed") val nTweak = toNat(tweak)
return serializePubkey(nPubkey) secp256k1_ec_pubkey_tweak_add(ctx, nPubkey.ptr, nTweak).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_tweak_add() failed")
return serializePubkey(nPubkey)
}
} }
} }
public override fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray { public override fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPubkey = allocPublicKey(pubkey) memScoped {
val nTweak = toNat(tweak) val nPubkey = allocPublicKey(pubkey)
secp256k1_ec_pubkey_tweak_mul(ctx, nPubkey.ptr, nTweak).requireSuccess("secp256k1_ec_pubkey_tweak_mul() failed") val nTweak = toNat(tweak)
return serializePubkey(nPubkey) secp256k1_ec_pubkey_tweak_mul(ctx, nPubkey.ptr, nTweak).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_tweak_mul() failed")
return serializePubkey(nPubkey)
}
} }
} }
public override fun pubKeyCombine(pubkeys: Array<ByteArray>): ByteArray { public override fun pubKeyCombine(pubkeys: Array<ByteArray>): ByteArray {
pubkeys.forEach { require(it.size == 33 || it.size == 65) } pubkeys.forEach { require(it.size == 33 || it.size == 65) }
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPubkeys = pubkeys.map { allocPublicKey(it).ptr } memScoped {
val combined = alloc<secp256k1_pubkey>() val nPubkeys = pubkeys.map { allocPublicKey(it).ptr }
secp256k1_ec_pubkey_combine(ctx, combined.ptr, nPubkeys.toCValues(), pubkeys.size.convert()).requireSuccess("secp256k1_ec_pubkey_combine() failed") val combined = alloc<secp256k1_pubkey>()
return serializePubkey(combined) secp256k1_ec_pubkey_combine(ctx, combined.ptr, nPubkeys.toCValues(), pubkeys.size.convert()).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_combine() failed")
return serializePubkey(combined)
}
} }
} }
public override fun ecdh(privkey: ByteArray, pubkey: ByteArray): ByteArray { public override fun ecdh(privkey: ByteArray, pubkey: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPubkey = allocPublicKey(pubkey) memScoped {
val nPrivkey = toNat(privkey) val nPubkey = allocPublicKey(pubkey)
val output = allocArray<UByteVar>(32) val nPrivkey = toNat(privkey)
secp256k1_ecdh(ctx, output, nPubkey.ptr, nPrivkey, null, null).requireSuccess("secp256k1_ecdh() failed") val output = allocArray<UByteVar>(32)
return output.readBytes(32) secp256k1_ecdh(ctx, output, nPubkey.ptr, nPrivkey, null, null).requireSuccess(callbackHandler, "secp256k1_ecdh() failed")
return output.readBytes(32)
}
} }
} }
public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray { public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray {
require(sig.size == 64) require(sig.size == 64)
require(message.size == 32) require(message.size == 32)
require(recid in 0..3) // we do not check that recid is valid, which should trigger our illegal callback handler to throw a Secp256k1IllegalCallbackException
memScoped { // require(recid in 0..3)
val nSig = toNat(sig)
val rSig = alloc<secp256k1_ecdsa_recoverable_signature>() CallbackHandler(ctx).use { callbackHandler ->
secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, rSig.ptr, nSig, recid).requireSuccess("secp256k1_ecdsa_recoverable_signature_parse_compact() failed") memScoped {
val nMessage = toNat(message) val nSig = toNat(sig)
val pubkey = alloc<secp256k1_pubkey>() val rSig = alloc<secp256k1_ecdsa_recoverable_signature>()
secp256k1_ecdsa_recover(ctx, pubkey.ptr, rSig.ptr, nMessage).requireSuccess("secp256k1_ecdsa_recover() failed") secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, rSig.ptr, nSig, recid).requireSuccess(callbackHandler, "secp256k1_ecdsa_recoverable_signature_parse_compact() failed")
return serializePubkey(pubkey) val nMessage = toNat(message)
val pubkey = alloc<secp256k1_pubkey>()
secp256k1_ecdsa_recover(ctx, pubkey.ptr, rSig.ptr, nMessage).requireSuccess(callbackHandler, "secp256k1_ecdsa_recover() failed")
return serializePubkey(pubkey)
}
} }
} }
public override fun compact2der(sig: ByteArray): ByteArray { public override fun compact2der(sig: ByteArray): ByteArray {
require(sig.size == 64) require(sig.size == 64)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nSig = allocSignature(sig) memScoped {
val natOutput = allocArray<UByteVar>(73) val nSig = allocSignature(sig)
val len = alloc<size_tVar>() val natOutput = allocArray<UByteVar>(73)
len.value = 73.convert() val len = alloc<size_tVar>()
secp256k1_ecdsa_signature_serialize_der(ctx, natOutput, len.ptr, nSig.ptr).requireSuccess("secp256k1_ecdsa_signature_serialize_der() failed") len.value = 73.convert()
return natOutput.readBytes(len.value.toInt()) secp256k1_ecdsa_signature_serialize_der(ctx, natOutput, len.ptr, nSig.ptr).requireSuccess(callbackHandler, "secp256k1_ecdsa_signature_serialize_der() failed")
return natOutput.readBytes(len.value.toInt())
}
} }
} }
@ -276,13 +320,15 @@ public object Secp256k1Native : Secp256k1 {
require(signature.size == 64) require(signature.size == 64)
require(data.size == 32) require(data.size == 32)
require(pub.size == 32) require(pub.size == 32)
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nPub = toNat(pub) memScoped {
val pubkey = alloc<secp256k1_xonly_pubkey>() val nPub = toNat(pub)
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed") val pubkey = alloc<secp256k1_xonly_pubkey>()
val nData = toNat(data) secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess(callbackHandler, "secp256k1_xonly_pubkey_parse() failed")
val nSig = toNat(signature) val nData = toNat(data)
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32, pubkey.ptr) == 1 val nSig = toNat(signature)
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32u, pubkey.ptr) == 1
}
} }
} }
@ -290,15 +336,17 @@ public object Secp256k1Native : Secp256k1 {
require(sec.size == 32) require(sec.size == 32)
require(data.size == 32) require(data.size == 32)
auxrand32?.let { require(it.size == 32) } auxrand32?.let { require(it.size == 32) }
memScoped { CallbackHandler(ctx).use { callbackHandler ->
val nSec = toNat(sec) memScoped {
val nData = toNat(data) val nSec = toNat(sec)
val nAuxrand32 = auxrand32?.let { toNat(it) } val nData = toNat(data)
val nSig = allocArray<UByteVar>(64) val nAuxrand32 = auxrand32?.let { toNat(it) }
val keypair = alloc<secp256k1_keypair>() val nSig = allocArray<UByteVar>(64)
secp256k1_keypair_create(ctx, keypair.ptr, nSec).requireSuccess("secp256k1_keypair_create() failed") val keypair = alloc<secp256k1_keypair>()
secp256k1_schnorrsig_sign32(ctx, nSig, nData, keypair.ptr, nAuxrand32).requireSuccess("secp256k1_ecdsa_sign() failed") secp256k1_keypair_create(ctx, keypair.ptr, nSec).requireSuccess(callbackHandler, "secp256k1_keypair_create() failed")
return nSig.readBytes(64) secp256k1_schnorrsig_sign32(ctx, nSig, nData, keypair.ptr, nAuxrand32).requireSuccess(callbackHandler, "secp256k1_ecdsa_sign() failed")
return nSig.readBytes(64)
}
} }
} }

View File

@ -276,7 +276,8 @@ class Secp256k1Test {
val pub1 = Secp256k1.ecdsaRecover(sig, message, 1) val pub1 = Secp256k1.ecdsaRecover(sig, message, 1)
assertTrue(pub.contentEquals(pub0) || pub.contentEquals(pub1)) assertTrue(pub.contentEquals(pub0) || pub.contentEquals(pub1))
assertFails { // this is a special case, ecdsaRecover explicitly does not check that recid is valid, which triggers our illegal callback handler
assertFailsWith(Secp256k1IllegalCallbackException::class) {
Secp256k1.ecdsaRecover(sig, message, 4) Secp256k1.ecdsaRecover(sig, message, 4)
} }
} }