diff --git a/pom.xml b/pom.xml
index 3ef1d507..99ad3f52 100644
--- a/pom.xml
+++ b/pom.xml
@@ -146,12 +146,12 @@
fr.acinq.bitcoin
bitcoin-kmp-jvm
- 0.29.0
+ 0.30.0
fr.acinq.secp256k1
secp256k1-kmp-jni-jvm
- 0.22.0
+ 0.23.0
org.scodec
diff --git a/src/main/scala/fr/acinq/bitcoin/scalacompat/Crypto.scala b/src/main/scala/fr/acinq/bitcoin/scalacompat/Crypto.scala
index bfb56357..8b6cd3d8 100644
--- a/src/main/scala/fr/acinq/bitcoin/scalacompat/Crypto.scala
+++ b/src/main/scala/fr/acinq/bitcoin/scalacompat/Crypto.scala
@@ -240,10 +240,6 @@ object Crypto {
def isDefinedHashTypeSignature(sig: ByteVector): Boolean = bitcoin.Crypto.isDefinedHashTypeSignature(sig.toArray)
- def compact2der(signature: ByteVector64): ByteVector = bitcoin.Crypto.compact2der(signature)
-
- def der2compact(signature: ByteVector): ByteVector64 = bitcoin.Crypto.der2compact(signature.toArray)
-
/**
* @param data data
* @param signature signature
diff --git a/src/main/scala/fr/acinq/bitcoin/scalacompat/Transaction.scala b/src/main/scala/fr/acinq/bitcoin/scalacompat/Transaction.scala
index e01ad5ca..1db20523 100644
--- a/src/main/scala/fr/acinq/bitcoin/scalacompat/Transaction.scala
+++ b/src/main/scala/fr/acinq/bitcoin/scalacompat/Transaction.scala
@@ -282,7 +282,7 @@ object Transaction extends BtcSerializer[Transaction] {
* @param amount amount of the output claimed by this tx input
* @param signatureVersion signature version (1: segwit, 0: pre-segwit)
* @param privateKey private key
- * @return the encoded signature of this tx for this specific tx input
+ * @return the encoded signature (DER + sighash byte) of this tx for this specific tx input
*/
def signInput(tx: Transaction, inputIndex: Int, previousOutputScript: ByteVector, sighashType: Int, amount: Satoshi, signatureVersion: Int, privateKey: PrivateKey): ByteVector = {
tx.signInput(inputIndex, previousOutputScript, sighashType, amount, signatureVersion, privateKey)
@@ -298,11 +298,18 @@ object Transaction extends BtcSerializer[Transaction] {
* @param amount amount of the output claimed by this tx input
* @param signatureVersion signature version (1: segwit, 0: pre-segwit)
* @param privateKey private key
- * @return the encoded signature of this tx for this specific tx input
+ * @return the encoded signature (DER + sighash byte) of this tx for this specific tx input
*/
def signInput(tx: Transaction, inputIndex: Int, previousOutputScript: Seq[ScriptElt], sighashType: Int, amount: Satoshi, signatureVersion: Int, privateKey: PrivateKey): ByteVector =
signInput(tx, inputIndex, Script.write(previousOutputScript), sighashType, amount, signatureVersion, privateKey)
+ /**
+ * @param sig ECDSA signature in compact format
+ * @param sighashType signature hash type, which will be appended to the signature
+ * @return an ECDSA signature in the format used in transaction witnesses: DER encoded followed by a sighash byte
+ */
+ def encodeWitnessEcdsaSig(sig: ByteVector64, sighashType: Int): ByteVector = ByteVector.view(fr.acinq.bitcoin.Transaction.encodeWitnessEcdsaSig(sig, sighashType))
+
/**
* Sign a taproot tx input, using the internal key path.
*
@@ -484,6 +491,36 @@ case class Transaction(version: Long, txIn: Seq[TxIn], txOut: Seq[TxOut], lockTi
scala2kmp(this).hashForSigningTaprootScriptPath(inputIndex, inputs.map(scala2kmp).asJava, sighashType, scala2kmp(tapleaf), annex_opt.map(scala2kmp).orNull)
}
+ /**
+ * sign a tx input
+ *
+ * @param inputIndex index of the tx input that is being processed
+ * @param previousOutputScript public key script of the output claimed by this tx input
+ * @param sighashType signature hash type, which will be appended to the signature
+ * @param amount amount of the output claimed by this tx input
+ * @param signatureVersion signature version (1: segwit, 0: pre-segwit)
+ * @param privateKey private key
+ * @return the encoded signature of this tx for this specific tx input in compact 64 bytes format
+ */
+ def signInputCompact(inputIndex: Int, previousOutputScript: ByteVector, sighashType: Int, amount: Satoshi, signatureVersion: Int, privateKey: PrivateKey): ByteVector64 = {
+ scala2kmp(this).signInputCompact(inputIndex, scala2kmp(previousOutputScript), sighashType, amount, signatureVersion, privateKey.priv)
+ }
+
+ /**
+ * sign a tx input
+ *
+ * @param inputIndex index of the tx input that is being processed
+ * @param previousOutputScript public key script of the output claimed by this tx input
+ * @param sighashType signature hash type, which will be appended to the signature
+ * @param amount amount of the output claimed by this tx input
+ * @param signatureVersion signature version (1: segwit, 0: pre-segwit)
+ * @param privateKey private key
+ * @return the encoded signature of this tx for this specific tx input in compact 64 bytes format
+ */
+ def signInputCompact(inputIndex: Int, previousOutputScript: Seq[ScriptElt], sighashType: Int, amount: Satoshi, signatureVersion: Int, privateKey: PrivateKey): ByteVector64 =
+ signInputCompact(inputIndex, Script.write(previousOutputScript), sighashType, amount, signatureVersion, privateKey)
+
+
/**
* sign a tx input
*
diff --git a/src/test/scala/fr/acinq/bitcoin/scalacompat/CryptoSpec.scala b/src/test/scala/fr/acinq/bitcoin/scalacompat/CryptoSpec.scala
index 0f157d03..7761f892 100644
--- a/src/test/scala/fr/acinq/bitcoin/scalacompat/CryptoSpec.scala
+++ b/src/test/scala/fr/acinq/bitcoin/scalacompat/CryptoSpec.scala
@@ -3,6 +3,7 @@ package fr.acinq.bitcoin.scalacompat
import fr.acinq.bitcoin.Base58.Prefix
import fr.acinq.bitcoin.scalacompat.Crypto._
import fr.acinq.bitcoin.{Base58, Base58Check}
+import fr.acinq.secp256k1.Secp256k1
import org.scalatest.FlatSpec
import scodec.bits._
@@ -157,7 +158,7 @@ class CryptoSpec extends FlatSpec {
dataset.map {
case (k, m, s) =>
- val sig: ByteVector = Crypto.compact2der(Crypto.sign(Crypto.sha256(ByteVector.view(m.getBytes("UTF-8"))), PrivateKey(k)))
+ val sig: ByteVector = ByteVector.view(Secp256k1.get().compact2der(Crypto.sign(Crypto.sha256(ByteVector.view(m.getBytes("UTF-8"))), PrivateKey(k)).toArray))
assert(sig == s)
}
}
diff --git a/src/test/scala/fr/acinq/bitcoin/scalacompat/Secp256k1Spec.scala b/src/test/scala/fr/acinq/bitcoin/scalacompat/Secp256k1Spec.scala
index 1e611a55..a52573c0 100644
--- a/src/test/scala/fr/acinq/bitcoin/scalacompat/Secp256k1Spec.scala
+++ b/src/test/scala/fr/acinq/bitcoin/scalacompat/Secp256k1Spec.scala
@@ -5,7 +5,7 @@ import fr.acinq.secp256k1.Secp256k1
import org.scalatest.FunSuite
import scodec.bits.ByteVector
-import scala.util.{Random, Try}
+import scala.util.Random
/**
* run this test with -Djava.library.path=$PATH_LIBSECP256K1_DIR where $PATH_LIBSECP256K1_DIR is a directory that
@@ -33,7 +33,7 @@ class Secp256k1Spec extends FunSuite {
Random.nextBytes(priv)
Random.nextBytes(data)
val sig1: ByteVector = Crypto.sign(ByteVector.view(data), PrivateKey(ByteVector.view(priv)))
- val sig2: ByteVector = ByteVector.view(nativeSecp256k1.get.sign(data, priv))
+ val sig2: ByteVector = ByteVector.view(nativeSecp256k1.get.sign(data, priv, null))
assert(sig1 == sig2)
}
}
diff --git a/src/test/scala/fr/acinq/bitcoin/scalacompat/SegwitSpec.scala b/src/test/scala/fr/acinq/bitcoin/scalacompat/SegwitSpec.scala
index 2002d6cf..9110f20d 100644
--- a/src/test/scala/fr/acinq/bitcoin/scalacompat/SegwitSpec.scala
+++ b/src/test/scala/fr/acinq/bitcoin/scalacompat/SegwitSpec.scala
@@ -2,6 +2,7 @@ package fr.acinq.bitcoin.scalacompat
import fr.acinq.bitcoin.scalacompat.Crypto.PrivateKey
import fr.acinq.bitcoin.{Base58, Base58Check, ScriptFlags, SigHash, SigVersion}
+import fr.acinq.secp256k1.Secp256k1
import org.scalatest.FunSuite
import scodec.bits._
@@ -30,7 +31,8 @@ class SegwitSpec extends FunSuite {
val priv = PrivateKey(hex"619c335025c7f4012e556c2a58b2506e30b8511b53ade95ea316fd8c3286feb901")
val pub = priv.publicKey
val sig = hex"304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee"
- assert(Crypto.verifySignature(hash, Crypto.der2compact(sig), pub))
+ val compact = ByteVector64(ByteVector(Secp256k1.get().der2compact(sig.toArray)))
+ assert(Crypto.verifySignature(hash, ByteVector64(compact), pub))
val sigScript = hex"4830450221008b9d1dc26ba6a9cb62127b02742fa9d754cd3bebf337f7a55d114c8e5cdd30be022040529b194ba3f9281a99f2b1c0a19c0489bc22ede944ccf4ecbab4cc618ef3ed01"
val tx1 = tx.updateSigScript(0, sigScript)