From 6515f03380ef1fdc6e65e4792fc5cf44ec94eb29 Mon Sep 17 00:00:00 2001 From: sstone Date: Mon, 15 Dec 2025 16:08:27 +0100 Subject: [PATCH 1/6] Update bitcoin-kmp (taproot tweak refactoring) and secp256k1-kmp --- pom.xml | 6 ++--- .../fr/acinq/bitcoin/scalacompat/Crypto.scala | 25 +++++++------------ .../bitcoin/scalacompat/KotlinUtils.scala | 20 +++------------ .../fr/acinq/bitcoin/scalacompat/Script.scala | 6 ----- .../bitcoin/scalacompat/TaprootSpec.scala | 12 ++++----- 5 files changed, 22 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index 596bdd94..6c6b4449 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ fr.acinq bitcoin-lib_2.13 jar - 0.45.2-SNAPSHOT + 0.46-SNAPSHOT Simple Scala Bitcoin library https://github.com/ACINQ/bitcoin-lib bitcoin-lib @@ -153,12 +153,12 @@ fr.acinq.bitcoin bitcoin-kmp-jvm - 0.28.1 + 0.29.0-SNAPSHOT fr.acinq.secp256k1 secp256k1-kmp-jni-jvm - 0.21.0 + 0.22.0-SNAPSHOT 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 35db3acb..bfb56357 100644 --- a/src/main/scala/fr/acinq/bitcoin/scalacompat/Crypto.scala +++ b/src/main/scala/fr/acinq/bitcoin/scalacompat/Crypto.scala @@ -7,21 +7,14 @@ import scodec.bits.ByteVector object Crypto { // @formatter:off - /** Specify how private keys are tweaked when creating Schnorr signatures. */ - sealed trait SchnorrTweak - object SchnorrTweak { - /** The private key is directly used, without any tweaks. */ - case object NoTweak extends SchnorrTweak - } - - sealed trait TaprootTweak extends SchnorrTweak + sealed trait TaprootTweak object TaprootTweak { /** The private key is tweaked with H_TapTweak(public key) (this is used for key path spending when there is no script tree). */ - case object NoScriptTweak extends TaprootTweak + case object KeyPathTweak extends TaprootTweak /** The private key is tweaked with H_TapTweak(public key || merkle_root) (this is used for key path spending when a script tree exists). */ - case class ScriptTweak(merkleRoot: ByteVector32) extends TaprootTweak - object ScriptTweak { - def apply(scriptTree: ScriptTree): ScriptTweak = ScriptTweak(scriptTree.hash()) + case class ScriptPathTweak(merkleRoot: ByteVector32) extends TaprootTweak + object ScriptPathTweak { + def apply(scriptTree: ScriptTree): ScriptPathTweak = ScriptPathTweak(scriptTree.hash()) } } // @formatter:on @@ -159,10 +152,10 @@ object Crypto { } /** Tweak this key with the merkle root of the given script tree. */ - def outputKey(scriptTree: ScriptTree): (XonlyPublicKey, Boolean) = outputKey(TaprootTweak.ScriptTweak(scriptTree)) + def outputKey(scriptTree: ScriptTree): (XonlyPublicKey, Boolean) = outputKey(TaprootTweak.ScriptPathTweak(scriptTree)) /** Tweak this key with the merkle root provided. */ - def outputKey(merkleRoot: ByteVector32): (XonlyPublicKey, Boolean) = outputKey(TaprootTweak.ScriptTweak(merkleRoot)) + def outputKey(merkleRoot: ByteVector32): (XonlyPublicKey, Boolean) = outputKey(TaprootTweak.ScriptPathTweak(merkleRoot)) /** * add a public key to this x-only key @@ -295,8 +288,8 @@ object Crypto { * the key (there is an extra "1" appended to the key) * @return a signature in compact format (64 bytes) */ - def signSchnorr(data: ByteVector32, privateKey: PrivateKey, schnorrTweak: SchnorrTweak = SchnorrTweak.NoTweak, auxrand32: Option[ByteVector32] = None): ByteVector64 = { - bitcoin.Crypto.signSchnorr(data, privateKey, scala2kmp(schnorrTweak), auxrand32.map(scala2kmp).orNull) + def signSchnorr(data: ByteVector32, privateKey: PrivateKey, schnorrTweak_opt: Option[TaprootTweak] = None, auxrand32: Option[ByteVector32] = None): ByteVector64 = { + bitcoin.Crypto.signSchnorr(data, privateKey, schnorrTweak_opt.map(scala2kmp).orNull, auxrand32.map(scala2kmp).orNull) } /** diff --git a/src/main/scala/fr/acinq/bitcoin/scalacompat/KotlinUtils.scala b/src/main/scala/fr/acinq/bitcoin/scalacompat/KotlinUtils.scala index 880ccc67..607c8755 100644 --- a/src/main/scala/fr/acinq/bitcoin/scalacompat/KotlinUtils.scala +++ b/src/main/scala/fr/acinq/bitcoin/scalacompat/KotlinUtils.scala @@ -65,25 +65,13 @@ object KotlinUtils { } implicit def kmp2scala(input: bitcoin.Crypto.TaprootTweak): TaprootTweak = input match { - case bitcoin.Crypto.TaprootTweak.NoScriptTweak.INSTANCE => TaprootTweak.NoScriptTweak - case tweak: bitcoin.Crypto.TaprootTweak.ScriptTweak => TaprootTweak.ScriptTweak(kmp2scala(tweak.getMerkleRoot)) - case _ => ??? // this cannot happen, but the compiler cannot know that there aren't other cases + case bitcoin.Crypto.TaprootTweak.KeyPathTweak.INSTANCE => TaprootTweak.KeyPathTweak + case tweak: bitcoin.Crypto.TaprootTweak.ScriptPathTweak => TaprootTweak.ScriptPathTweak(kmp2scala(tweak.getMerkleRoot)) } implicit def scala2kmp(input: TaprootTweak): bitcoin.Crypto.TaprootTweak = input match { - case TaprootTweak.NoScriptTweak => bitcoin.Crypto.TaprootTweak.NoScriptTweak.INSTANCE - case tweak: TaprootTweak.ScriptTweak => new bitcoin.Crypto.TaprootTweak.ScriptTweak(scala2kmp(tweak.merkleRoot)) - } - - implicit def kmp2scala(input: bitcoin.Crypto.SchnorrTweak): SchnorrTweak = input match { - case bitcoin.Crypto.SchnorrTweak.NoTweak.INSTANCE => SchnorrTweak.NoTweak - case tweak: bitcoin.Crypto.TaprootTweak => kmp2scala(tweak) - case _ => ??? // this cannot happen, but the compiler cannot know that there aren't other cases - } - - implicit def scala2kmp(input: SchnorrTweak): bitcoin.Crypto.SchnorrTweak = input match { - case SchnorrTweak.NoTweak => bitcoin.Crypto.SchnorrTweak.NoTweak.INSTANCE - case tweak: TaprootTweak => scala2kmp(tweak) + case TaprootTweak.KeyPathTweak => bitcoin.Crypto.TaprootTweak.KeyPathTweak.INSTANCE + case tweak: TaprootTweak.ScriptPathTweak => new bitcoin.Crypto.TaprootTweak.ScriptPathTweak(scala2kmp(tweak.merkleRoot)) } implicit def kmp2scala(input: bitcoin.TxIn): TxIn = TxIn(input.outPoint, input.signatureScript, input.sequence, input.witness) diff --git a/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala b/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala index f28f24aa..225310d9 100644 --- a/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala +++ b/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala @@ -165,12 +165,6 @@ object Script { */ def witnessPay2wpkh(pubKey: PublicKey, sig: ByteVector): ScriptWitness = bitcoin.Script.witnessPay2wpkh(pubKey, sig) - /** - * @param outputKey public key exposed by the taproot script (tweaked based on the tapscripts). - * @return a pay-to-taproot script. - */ - def pay2tr(outputKey: XonlyPublicKey): Seq[ScriptElt] = bitcoin.Script.pay2tr(outputKey.pub).asScala.map(kmp2scala).toList - /** * @param internalKey internal public key that will be tweaked with the [scripts] provided. * @param scripts_opt optional spending scripts that can be used instead of key-path spending. diff --git a/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala b/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala index e5b5552b..38824b9c 100644 --- a/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala +++ b/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala @@ -15,9 +15,9 @@ class TaprootSpec extends FunSuite { val key = DeterministicWallet.derivePrivateKey(master, "86'/1'/0'/0/1") val internalKey = key.publicKey.xOnly val script = Script.pay2tr(internalKey, scripts_opt = None) - val (outputKey, _) = internalKey.outputKey(TaprootTweak.NoScriptTweak) + val (outputKey, _) = internalKey.outputKey(TaprootTweak.KeyPathTweak) assert("tb1phlhs7afhqzkgv0n537xs939s687826vn8l24ldkrckvwsnlj3d7qj6u57c" == Bech32.encodeWitnessAddress("tb", 1, outputKey.pub.value.toByteArray)) - assert(script == Script.pay2tr(outputKey)) + assert(addressFromPublicKeyScript(Block.Testnet3GenesisBlock.hash, script).contains("tb1phlhs7afhqzkgv0n537xs939s687826vn8l24ldkrckvwsnlj3d7qj6u57c")) // tx sends to tb1phlhs7afhqzkgv0n537xs939s687826vn8l24ldkrckvwsnlj3d7qj6u57c val tx = Transaction.read( @@ -41,23 +41,23 @@ class TaprootSpec extends FunSuite { assert(Crypto.verifySignatureSchnorr(hash, sig, outputKey)) // re-create signature - val ourSig = Crypto.signSchnorr(hash, key.privateKey, TaprootTweak.NoScriptTweak) + val ourSig = Crypto.signSchnorr(hash, key.privateKey, Some(TaprootTweak.KeyPathTweak)) assert(Crypto.verifySignatureSchnorr(hash, ourSig, outputKey)) assert(Secp256k1.get().verifySchnorr(ourSig.toArray, hash.toArray, outputKey.pub.value.toByteArray)) // setting auxiliary random data to all-zero yields the same result as not setting any auxiliary random data - val ourSig1 = Crypto.signSchnorr(hash, key.privateKey, TaprootTweak.NoScriptTweak, Some(ByteVector32.Zeroes)) + val ourSig1 = Crypto.signSchnorr(hash, key.privateKey, Some(TaprootTweak.KeyPathTweak), Some(ByteVector32.Zeroes)) assert(ourSig == ourSig1) // setting auxiliary random data to a non-zero value yields a different result - val ourSig2 = Crypto.signSchnorr(hash, key.privateKey, TaprootTweak.NoScriptTweak, Some(ByteVector32.One)) + val ourSig2 = Crypto.signSchnorr(hash, key.privateKey, Some(TaprootTweak.KeyPathTweak), Some(ByteVector32.One)) assert(ourSig != ourSig2) } test("send to and spend from taproot addresses") { val privateKey = PrivateKey(ByteVector32.fromValidHex("0101010101010101010101010101010101010101010101010101010101010101")) val internalKey = privateKey.publicKey.xOnly - val (outputKey, _) = internalKey.outputKey(TaprootTweak.NoScriptTweak) + val (outputKey, _) = internalKey.outputKey(TaprootTweak.KeyPathTweak) val address = Bech32.encodeWitnessAddress("tb", 1, outputKey.pub.value.toByteArray) assert("tb1p33wm0auhr9kkahzd6l0kqj85af4cswn276hsxg6zpz85xe2r0y8snwrkwy" == address) From b5d9a0d505cb5c3bc5b6147e1c9e9faa7c96fe4e Mon Sep 17 00:00:00 2001 From: sstone Date: Tue, 16 Dec 2025 10:21:30 +0100 Subject: [PATCH 2/6] Publish snapshots to https://central.sonatype.com/repository/maven-snapshots --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index 6c6b4449..43adc389 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,13 @@ https://github.com/ACINQ/bitcoin-lib bitcoin-lib + + + central-snapshots + https://central.sonatype.com/repository/maven-snapshots + + + 2020-01-01T00:00:00Z UTF-8 From 4458592c39a9172dd1e89ced3eb0a40d02255786 Mon Sep 17 00:00:00 2001 From: sstone Date: Thu, 18 Dec 2025 14:36:53 +0100 Subject: [PATCH 3/6] Use bitcoin-kmp at 2ffe94df7f8de86c34b660e6566744498e0d99a1 --- pom.xml | 2 +- .../fr/acinq/bitcoin/scalacompat/Script.scala | 16 ++++++++++++++-- .../acinq/bitcoin/scalacompat/Musig2Spec.scala | 5 +++-- .../acinq/bitcoin/scalacompat/TaprootSpec.scala | 9 +++++---- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 43adc389..035fbe70 100644 --- a/pom.xml +++ b/pom.xml @@ -165,7 +165,7 @@ fr.acinq.secp256k1 secp256k1-kmp-jni-jvm - 0.22.0-SNAPSHOT + 0.22.0 org.scodec diff --git a/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala b/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala index 225310d9..41b08bc3 100644 --- a/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala +++ b/src/main/scala/fr/acinq/bitcoin/scalacompat/Script.scala @@ -167,9 +167,21 @@ object Script { /** * @param internalKey internal public key that will be tweaked with the [scripts] provided. - * @param scripts_opt optional spending scripts that can be used instead of key-path spending. + * @param scriptsRoot spending scripts that can be used instead of key-path spending. */ - def pay2tr(internalKey: XonlyPublicKey, scripts_opt: Option[ScriptTree]): Seq[ScriptElt] = bitcoin.Script.pay2tr(internalKey.pub, scripts_opt.map(scala2kmp).orNull).asScala.map(kmp2scala).toList + def pay2tr(internalKey: XonlyPublicKey, scriptsRoot: ByteVector32): Seq[ScriptElt] = bitcoin.Script.pay2tr(internalKey.pub, scriptsRoot).asScala.map(kmp2scala).toList + + /** + * @param internalKey internal public key that will be tweaked with the [scripts] provided. + * @param scripts spending scripts that can be used instead of key-path spending. + */ + def pay2tr(internalKey: XonlyPublicKey, scripts: ScriptTree): Seq[ScriptElt] = pay2tr(internalKey, scripts.hash()) + + /** + * @param internalKey internal public key that will be tweaked with the provided [taprootTweak]. + * @param taprootTweak tweak to apply to [internalKey]. + */ + def pay2tr(internalKey: XonlyPublicKey, taprootTweak: Crypto.TaprootTweak): Seq[ScriptElt] = bitcoin.Script.pay2tr(internalKey.pub, taprootTweak).asScala.map(kmp2scala).toList def isPay2tr(script: Seq[ScriptElt]): Boolean = bitcoin.Script.isPay2tr(script.map(scala2kmp).asJava) diff --git a/src/test/scala/fr/acinq/bitcoin/scalacompat/Musig2Spec.scala b/src/test/scala/fr/acinq/bitcoin/scalacompat/Musig2Spec.scala index 55f24e1f..ec7e4a9b 100644 --- a/src/test/scala/fr/acinq/bitcoin/scalacompat/Musig2Spec.scala +++ b/src/test/scala/fr/acinq/bitcoin/scalacompat/Musig2Spec.scala @@ -1,6 +1,7 @@ package fr.acinq.bitcoin.scalacompat import fr.acinq.bitcoin.scalacompat.Crypto.PrivateKey +import fr.acinq.bitcoin.scalacompat.Crypto.TaprootTweak.KeyPathTweak import fr.acinq.bitcoin.{ScriptFlags, SigHash} import org.scalatest.FunSuite import scodec.bits.{ByteVector, HexStringSyntax} @@ -19,7 +20,7 @@ class Musig2Spec extends FunSuite { val internalPubKey = Musig2.aggregateKeys(Seq(alicePubKey, bobPubKey)) // This tx sends to a taproot script that doesn't contain any script path. - val tx = Transaction(2, Nil, Seq(TxOut(10_000 sat, Script.pay2tr(internalPubKey, scripts_opt = None))), 0) + val tx = Transaction(2, Nil, Seq(TxOut(10_000 sat, Script.pay2tr(internalPubKey, KeyPathTweak))), 0) // This tx spends the previous tx with Alice and Bob's signatures. val spendingTx = Transaction(2, Seq(TxIn(OutPoint(tx, 0), ByteVector.empty, 0)), Seq(TxOut(10_000 sat, Script.pay2wpkh(alicePubKey))), 0) @@ -59,7 +60,7 @@ class Musig2Spec extends FunSuite { // The internal pubkey is the musig2 aggregation of the user's and server's public keys: it does not depend upon the user's refund's key. val aggregatedKey = Musig2.aggregateKeys(Seq(userPublicKey, serverPublicKey)) // It is tweaked with the script's merkle root to get the pubkey that will be exposed. - val pubkeyScript = Script.pay2tr(aggregatedKey, Some(scriptTree)) + val pubkeyScript = Script.pay2tr(aggregatedKey, scriptTree) val swapInTx = Transaction( version = 2, diff --git a/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala b/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala index 38824b9c..79d6e3a2 100644 --- a/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala +++ b/src/test/scala/fr/acinq/bitcoin/scalacompat/TaprootSpec.scala @@ -1,5 +1,6 @@ package fr.acinq.bitcoin.scalacompat +import fr.acinq.bitcoin.scalacompat.Crypto.TaprootTweak.KeyPathTweak import fr.acinq.bitcoin.scalacompat.Crypto.{PrivateKey, PublicKey, TaprootTweak} import fr.acinq.bitcoin.scalacompat.KotlinUtils._ import fr.acinq.bitcoin.{Bech32, ScriptFlags, SigHash, SigVersion} @@ -14,7 +15,7 @@ class TaprootSpec extends FunSuite { val (_, master) = DeterministicWallet.ExtendedPrivateKey.decode("tprv8ZgxMBicQKsPeQQADibg4WF7mEasy3piWZUHyThAzJCPNgMHDVYhTCVfev3jFbDhcYm4GimeFMbbi9z1d9rfY1aL5wfJ9mNebQ4thJ62EJb") val key = DeterministicWallet.derivePrivateKey(master, "86'/1'/0'/0/1") val internalKey = key.publicKey.xOnly - val script = Script.pay2tr(internalKey, scripts_opt = None) + val script = Script.pay2tr(internalKey, KeyPathTweak) val (outputKey, _) = internalKey.outputKey(TaprootTweak.KeyPathTweak) assert("tb1phlhs7afhqzkgv0n537xs939s687826vn8l24ldkrckvwsnlj3d7qj6u57c" == Bech32.encodeWitnessAddress("tb", 1, outputKey.pub.value.toByteArray)) assert(addressFromPublicKeyScript(Block.Testnet3GenesisBlock.hash, script).contains("tb1phlhs7afhqzkgv0n537xs939s687826vn8l24ldkrckvwsnlj3d7qj6u57c")) @@ -65,7 +66,7 @@ class TaprootSpec extends FunSuite { val tx = Transaction.read( "02000000000101bf77ef36f2c0f32e0822cef0514948254997495a34bfba7dd4a73aabfcbb87900000000000fdffffff02c2c2000000000000160014b5c3dbfeb8e7d0c809c3ba3f815fd430777ef4be50c30000000000002251208c5db7f797196d6edc4dd7df6048f4ea6b883a6af6af032342088f436543790f0140583f758bea307216e03c1f54c3c6088e8923c8e1c89d96679fb00de9e808a79d0fba1cc3f9521cb686e8f43fb37cc6429f2e1480c70cc25ecb4ac0dde8921a01f1f70000" ) - assert(Script.pay2tr(internalKey, scripts_opt = None) == Script.parse(tx.txOut(1).publicKeyScript)) + assert(Script.pay2tr(internalKey, KeyPathTweak) == Script.parse(tx.txOut(1).publicKeyScript)) // we want to spend val Right(outputScript) = addressToPublicKeyScript(Block.Testnet3GenesisBlock.hash, "tb1pn3g330w4n5eut7d4vxq0pp303267qc6vg8d2e0ctjuqre06gs3yqnc5yx0") @@ -157,7 +158,7 @@ class TaprootSpec extends FunSuite { val internalPubkey = PublicKey.fromBin(ByteVector.fromValidHex("0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")).xOnly // funding tx sends to our tapscript - val fundingTx = Transaction(version = 2, txIn = Nil, txOut = Seq(TxOut(Satoshi(1000000), Script.pay2tr(internalPubkey, Some(scriptTree)))), lockTime = 0) + val fundingTx = Transaction(version = 2, txIn = Nil, txOut = Seq(TxOut(Satoshi(1000000), Script.pay2tr(internalPubkey, scriptTree))), lockTime = 0) // create an unsigned transaction val tmp = Transaction( @@ -213,7 +214,7 @@ class TaprootSpec extends FunSuite { val (tweakedKey, _) = internalPubkey.outputKey(scriptTree) // this is the tapscript we send funds to - val script = Script.pay2tr(internalPubkey, Some(scriptTree)) + val script = Script.pay2tr(internalPubkey, scriptTree) val bip350Address = Bech32.encodeWitnessAddress(Bech32.hrp(blockchain), 1.toByte, tweakedKey.pub.value.toByteArray) assert(bip350Address == "tb1p78gx95syx0qz8w5nftk8t7nce78zlpqpsxugcvq5xpfy4tvn6rasd7wk0y") val Right(sweepPublicKeyScript) = addressToPublicKeyScript(blockchain, "tb1qxy9hhxkw7gt76qrm4yzw4j06gkk4evryh8ayp7") From c53b8cec1d43736a6bf34f07629e28bcfd6f9c76 Mon Sep 17 00:00:00 2001 From: sstone Date: Thu, 18 Dec 2025 15:35:25 +0100 Subject: [PATCH 4/6] Use bitcoin-kmp 0.29.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 035fbe70..1390a3ea 100644 --- a/pom.xml +++ b/pom.xml @@ -160,7 +160,7 @@ fr.acinq.bitcoin bitcoin-kmp-jvm - 0.29.0-SNAPSHOT + 0.29.0 fr.acinq.secp256k1 From dd16446340d8a9b5e19409b8c530705cb08f04bd Mon Sep 17 00:00:00 2001 From: sstone Date: Thu, 18 Dec 2025 15:39:37 +0100 Subject: [PATCH 5/6] Set version to 0.46 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1390a3ea..43e98489 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ fr.acinq bitcoin-lib_2.13 jar - 0.46-SNAPSHOT + 0.46 Simple Scala Bitcoin library https://github.com/ACINQ/bitcoin-lib bitcoin-lib From c6e3eee3f1e47ae9f3d04f0e550da9d9acb8eaca Mon Sep 17 00:00:00 2001 From: sstone Date: Thu, 18 Dec 2025 15:54:08 +0100 Subject: [PATCH 6/6] Remove sonatype snapshot repository We can always add it back for PR that need to test against snapshot dependencies. --- pom.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pom.xml b/pom.xml index 43e98489..26e49133 100644 --- a/pom.xml +++ b/pom.xml @@ -47,20 +47,6 @@ - - - central-snapshots - Sonatype Central Portal (snapshots) - https://central.sonatype.com/repository/maven-snapshots - - false - - - true - - - -