What changed, and why it matters
This commit updates Eclair's underlying Bitcoin library from version 0.47 to 0.48 and makes small code adjustments to match the new library's API. The changes touch how private keys are derived and how test data is converted. There is no direct evidence in the commit that this fixes a security vulnerability, but library updates can include bug fixes or improvements that affect cryptographic handling.
Review the bitcoin-lib 0.48 release notes and changelog to determine whether this version bump addresses any security issues. Treat as a routine dependency update unless the upstream library release discloses security fixes.
Security signals we found
Dependency version bump of cryptographic Bitcoin library
Private key derivation code modified
Taproot/MuSig2 test vector code adjusted
Evidence from the diff
The commit bumps fr.acinq:bitcoin-lib from 0.47 to 0.48 and updates Maven checksums. Code changes replace the static helper fr.acinq.bitcoin.DeterministicWallet.derivePrivateKey(master.priv, keypath.keyPath) with the instance method master.priv.derivePrivateKey(keypath.keyPath), and adjust a test vector to call .toArrayUnsafe when constructing a musig2.SecretNonce. These are API-adaptation changes consistent with a new library version. The commit message does not describe security relevance, and no advisory or CVE is referenced.
Changed components
pom.xml dependency versionLocalOnChainKeyManager.scala private key derivation for p2wpkh and p2tr signingTestVectorsSpec.scala MuSig2 secret nonce constructionInspect captured patch +8 / −4
diff --git a/.mvn/checksums/checksums-central.sha256 b/.mvn/checksums/checksums-central.sha256
index 302b72a..f5296bb 100644
--- a/.mvn/checksums/checksums-central.sha256
+++ b/.mvn/checksums/checksums-central.sha256
@@ -29,6 +29,7 @@
05779149872544a527ee8a38558a9170979532f4806f4fe3cf893a10768a8fb2 com/fasterxml/jackson/core/jackson-databind/2.12.7.1/jackson-databind-2.12.7.1.pom
06242d1c9a37bb85f2119b7354c1c9760759a350b60e041438205467f4092efb com/softwaremill/sttp/model/core_2.13/1.5.5/core_2.13-1.5.5.jar
06411cc68ddad00308cfe759ef6dd78ca1f10633de93aae4f1ba256928026599 org/apache/maven/maven/3.8.6/maven-3.8.6.pom
+0652cb411dc3a0c3b6c29dc3cf4b0b8c15656fc555293102f7d5aeca43e8524f fr/acinq/bitcoin-lib_2.13/0.48/bitcoin-lib_2.13-0.48.jar
0670b605255f7dc9a454daaec7912918ccf1b5475cbfca374363b51fcfd4ea00 org/codehaus/plexus/plexus-component-annotations/2.1.0/plexus-component-annotations-2.1.0.pom
06aa5d1ac068f2f809530f3ff53fb5c8c940152a253623d0b53c4f53f5a13a3d com/google/guava/guava-parent/32.1.1-jre/guava-parent-32.1.1-jre.pom
06cfb3e43bb5d417aff2418dbbf023884e644f7233ba841b47602662e1be7f68 org/apache/maven/plugins/maven-wrapper-plugin/3.3.2/maven-wrapper-plugin-3.3.2.jar
@@ -390,6 +391,7 @@
4f8cfe457741689e3750f95c92987cdc3bbb625e7dbf341601098136935cb5f4 com/softwaremill/sttp/shared/core_2.13/1.3.13/core_2.13-1.3.13.pom
4ff2f359e2a6595d7b709ca1de43ed6da8c2cf67fe8b78f334e10f27c21c4361 org/json4s/json4s-scalap_2.13/4.0.6/json4s-scalap_2.13-4.0.6.jar
505777efcfb0c93baee9514c949b061c3d2f66c11d1e1d2c73a84995344dcd8c com/softwaremill/sttp/client3/json4s_2.13/3.8.16/json4s_2.13-3.8.16.pom
+5059b73fa5a75348675c6ebd55d2e3c92eb6e9c0809674e20e09430014f90883 fr/acinq/bitcoin-lib_2.13/0.48/bitcoin-lib_2.13-0.48.pom
508c83c62c344f6f7ee28f47b88a8797d6116d043bfd1ca0576c828dd1df2880 org/checkerframework/checker-qual/3.49.5/checker-qual-3.49.5.jar
50d2a59155284109a708675b52ebb4598500e43693967cff1401cb26b97f8853 org/glassfish/javax.json/1.1.4/javax.json-1.1.4.pom
50d699f86369802baf2cd16c31d936ad8f0c1a8976120cd1dc3dc70c8abed99a org/apache/maven/doxia/doxia-sink-api/1.0/doxia-sink-api-1.0.pom
@@ -455,6 +457,7 @@
5ca374eb4e6194ec0cd7004366decd39d4d048145a6380f99741a9414f38cebb org/apache/maven/maven-model-builder/3.8.6/maven-model-builder-3.8.6.jar
5cb1e9f9cf0be011487545694ff0a178237c6bfcbb21c97865cdc52c60b9347a com/jcraft/jzlib/1.1.1/jzlib-1.1.1.jar
5cecc8bcb58d45e2a57ccccaad5d520abf0e81dea2be56ec1ed38c182cff4bd0 io/kamon/kamon-apm-reporter_2.13/2.7.4/kamon-apm-reporter_2.13-2.7.4.pom
+5e0de676193687b752389bc65f8eb239669a13b1e8bb07c82eb103a6a4da1697 fr/acinq/bitcoin/bitcoin-kmp-jvm/0.31.0/bitcoin-kmp-jvm-0.31.0.pom
5e583878df905b5f33a230ef690a52b8f19dab9cc892bedee069f3d8af4e960a org/codehaus/plexus/plexus-utils/3.3.1/plexus-utils-3.3.1.pom
5e93a63b3042023e558dcbeb19914ce82e6a6fbccdbd68797f80b135121a8bde org/apache/maven/shared/file-management/3.1.0/file-management-3.1.0.pom
5f32ecab9c8f6dff1f9e41b853e40d8f23a2508219154ef67cc00d4556f5f5dd org/eclipse/sisu/sisu-inject/0.3.5/sisu-inject-0.3.5.pom
@@ -516,6 +519,7 @@
6d80b060de7e395e07bf90f9a14add0f80425add4016c89d7df91c9062717a20 org/apache/maven/surefire/surefire-booter/3.1.2/surefire-booter-3.1.2.jar
6da6d5e61be60d77a7eea6c7d0b8ac3cc35ca73cef3cbff97d5982006553786d commons-collections/commons-collections/3.2/commons-collections-3.2.pom
6df4b5b76d9062017664ad0ca285e57154ae803607cb89c970b39cc0e016abb0 org/bouncycastle/bcprov-jdk15on/1.70/bcprov-jdk15on-1.70.pom
+6e3b52b643baa4f23acf86cfe98363c902b723d62b3020a898e2d4e40aa6dfe8 fr/acinq/bitcoin/bitcoin-kmp-jvm/0.31.0/bitcoin-kmp-jvm-0.31.0.jar
6eba0902efd899aec0d8d19ac3cbc53123cd41139fe0e1d29cc5c874a791b9de org/eclipse/sisu/sisu-plexus/0.3.5/sisu-plexus-0.3.5.pom
6ec96f889bc29250f90b167c14e547f1b05aa23565c63f9079595befbde816bb org/codehaus/plexus/plexus/3.3.1/plexus-3.3.1.pom
6f819947a2a773792dc91d17f906e22113bfb2fefb6b64dec836175715d7402a org/apache/maven/plugins/maven-compiler-plugin/3.13.0/maven-compiler-plugin-3.13.0.jar
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalOnChainKeyManager.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalOnChainKeyManager.scala
index 790d083..3b888c3 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalOnChainKeyManager.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalOnChainKeyManager.scala
@@ -268,7 +268,7 @@ class LocalOnChainKeyManager(override val walletName: String, seed: ByteVector,
// Check that we're signing a p2wpkh input and that the keypath is provided and correct.
require(input.getDerivationPaths.size() == 1, "bip32 derivation path is missing: bitcoin core may be malicious")
val (pub, keypath) = input.getDerivationPaths.asScala.toSeq.head
- val priv = fr.acinq.bitcoin.DeterministicWallet.derivePrivateKey(master.priv, keypath.keyPath).getPrivateKey
+ val priv = master.priv.derivePrivateKey(keypath.keyPath).getPrivateKey
require(priv.publicKey() == pub, s"derived public key doesn't match (expected=$pub actual=${priv.publicKey()}): bitcoin core may be malicious")
val expectedScript = ByteVector(Script.write(Script.pay2wpkh(pub)))
require(kmp2scala(input.getWitnessUtxo.publicKeyScript) == expectedScript, s"script mismatch (expected=$expectedScript, actual=${input.getWitnessUtxo.publicKeyScript}): bitcoin core may be malicious")
@@ -305,7 +305,7 @@ class LocalOnChainKeyManager(override val walletName: String, seed: ByteVector,
// Check that we're signing a p2tr input and that the keypath is provided and correct.
require(input.getTaprootDerivationPaths.size() == 1, "bip32 derivation path is missing: bitcoin core may be malicious")
val (pub, keypath) = input.getTaprootDerivationPaths.asScala.toSeq.head
- val priv = fr.acinq.bitcoin.DeterministicWallet.derivePrivateKey(master.priv, keypath.keyPath).getPrivateKey
+ val priv = master.priv.derivePrivateKey(keypath.keyPath).getPrivateKey
require(priv.publicKey().xOnly() == pub, s"derived public key doesn't match (expected=$pub actual=${priv.publicKey().xOnly()}): bitcoin core may be malicious")
val expectedScript = Script.write(Script.pay2tr(pub, KeyPathTweak))
require(kmp2scala(input.getWitnessUtxo.publicKeyScript) == expectedScript, s"script mismatch (expected=$expectedScript, actual=${input.getWitnessUtxo.publicKeyScript}): bitcoin core may be malicious")
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala
index 0e5e3d9..5421e5a 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala
@@ -584,7 +584,7 @@ class SimpleTaprootCommitmentsTestVectorSpec extends AnyFunSuite {
val uncompressedPublicKey = PublicKey(serialized.takeRight(33)).toUncompressedBin
val publicKeyX = uncompressedPublicKey.drop(1).take(32).reverse
val publicKeyY = uncompressedPublicKey.takeRight(32).reverse
- val sec = new fr.acinq.bitcoin.crypto.musig2.SecretNonce(KotlinUtils.scala2kmp(hex"220EDCF1" ++ serialized.take(64) ++ publicKeyX ++ publicKeyY))
+ val sec = new fr.acinq.bitcoin.crypto.musig2.SecretNonce((hex"220EDCF1" ++ serialized.take(64) ++ publicKeyX ++ publicKeyY).toArrayUnsafe)
SecretNonce(sec)
}
diff --git a/pom.xml b/pom.xml
index 83224d9..4ee8291 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,7 +71,7 @@
<akka.version>2.6.20</akka.version>
<akka.http.version>10.2.7</akka.http.version>
<sttp.version>3.8.16</sttp.version>
- <bitcoinlib.version>0.47</bitcoinlib.version>
+ <bitcoinlib.version>0.48</bitcoinlib.version>
<guava.version>32.1.1-jre</guava.version>
<kamon.version>2.7.4</kamon.version>
<kanela-agent.version>1.0.18</kanela-agent.version>
Why this scored 22/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.