Skip to content

Commit 194f673

Browse files
authored
Update Bitcoin Core to v28.x (#2962)
Update Bitcoin Core to v28.x. This releases contains the following interesting features: - automatic utxo unlocking on wallet conflicts - support for testnet4 - 1-parent 1-child package relay (channel force-close) - `max_tx_weight` parameter to `fundrawtransaction`
1 parent 3aac8da commit 194f673

File tree

6 files changed

+29
-26
lines changed

6 files changed

+29
-26
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ This means that instead of re-implementing them, Eclair benefits from the verifi
6262

6363
* Eclair needs a _synchronized_, _segwit-ready_, **_zeromq-enabled_**, _wallet-enabled_, _non-pruning_, _tx-indexing_ [Bitcoin Core](https://github.com/bitcoin/bitcoin) node.
6464
* You must configure your Bitcoin node to use `bech32` or `bech32m` (segwit) addresses. If your wallet has "non-segwit UTXOs" (outputs that are neither `p2sh-segwit`, `bech32` or `bech32m`), you must send them to a `bech32` or `bech32m` address before running Eclair.
65-
* Eclair requires Bitcoin Core 27.2 or higher. If you are upgrading an existing wallet, you may need to create a new address and send all your funds to that address.
65+
* Eclair requires Bitcoin Core 28.1 or higher. If you are upgrading an existing wallet, you may need to create a new address and send all your funds to that address.
6666

6767
Run bitcoind with the following minimal `bitcoin.conf`:
6868

docs/release-notes/eclair-vnext.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
## Major changes
66

7+
### Update minimal version of Bitcoin Core
8+
9+
With this release, eclair requires using Bitcoin Core 28.1.
10+
Newer versions of Bitcoin Core may be used, but have not been extensively tested.
11+
712
### Simplified mutual close
813

914
This release includes support for the latest [mutual close protocol](https://github.com/lightning/bolts/pull/1205).

eclair-core/pom.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@
8787
<activeByDefault>true</activeByDefault>
8888
</activation>
8989
<properties>
90-
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-27.2/bitcoin-27.2-x86_64-linux-gnu.tar.gz</bitcoind.url>
91-
<bitcoind.sha256>acc223af46c178064c132b235392476f66d486453ddbd6bca6f1f8411547da78</bitcoind.sha256>
90+
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-28.1/bitcoin-28.1-x86_64-linux-gnu.tar.gz</bitcoind.url>
91+
<bitcoind.sha256>07f77afd326639145b9ba9562912b2ad2ccec47b8a305bd075b4f4cb127b7ed7</bitcoind.sha256>
9292
</properties>
9393
</profile>
9494
<profile>
@@ -99,8 +99,8 @@
9999
</os>
100100
</activation>
101101
<properties>
102-
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-27.2/bitcoin-27.2-x86_64-apple-darwin.tar.gz</bitcoind.url>
103-
<bitcoind.sha256>6ebc56ca1397615d5a6df2b5cf6727b768e3dcac320c2d5c2f321dcaabc7efa2</bitcoind.sha256>
102+
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-28.1/bitcoin-28.1-x86_64-apple-darwin.tar.gz</bitcoind.url>
103+
<bitcoind.sha256>c85d1a0ebedeff43b99db2c906b50f14547b84175a4d0ebb039a9809789af280</bitcoind.sha256>
104104
</properties>
105105
</profile>
106106
<profile>
@@ -111,8 +111,8 @@
111111
</os>
112112
</activation>
113113
<properties>
114-
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-27.2/bitcoin-27.2-win64.zip</bitcoind.url>
115-
<bitcoind.sha256>82e18f768aa5962b3c002d7f5d6ec9338896804f48406af4b5054c927575dbdf</bitcoind.sha256>
114+
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-28.1/bitcoin-28.1-win64.zip</bitcoind.url>
115+
<bitcoind.sha256>2d636ad562b347c96d36870d6ed810f4a364f446ca208258299f41048b35eab0</bitcoind.sha256>
116116
</properties>
117117
</profile>
118118
</profiles>

eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ class Setup(val datadir: File,
188188
await(getBitcoinStatus(bitcoinClient), 30 seconds, "bitcoind did not respond after 30 seconds")
189189
}
190190
logger.info(s"bitcoind version=${bitcoinStatus.version}")
191-
assert(bitcoinStatus.version >= 270200, "Eclair requires Bitcoin Core 27.2 or higher")
191+
assert(bitcoinStatus.version >= 280100, "Eclair requires Bitcoin Core 28.1 or higher")
192192
bitcoinStatus.unspentAddresses.foreach { address =>
193193
val isSegwit = addressToPublicKeyScript(bitcoinStatus.chainHash, address).map(script => Script.isNativeWitnessScript(script)).getOrElse(false)
194194
assert(isSegwit, s"Your wallet contains non-segwit UTXOs (e.g. address=$address). You must send those UTXOs to a segwit address to use Eclair (check out our README for more details).")

eclair-core/src/test/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreClientSpec.scala

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -500,34 +500,38 @@ class BitcoinCoreClientSpec extends TestKitBaseClass with BitcoindService with A
500500
val pubkeyScript = Script.write(Script.pay2wsh(Scripts.multiSig2of2(randomKey().publicKey, randomKey().publicKey)))
501501
val bitcoinClient = makeBitcoinCoreClient()
502502

503-
// create a huge tx so we make sure it has > 2 inputs
503+
// Create a huge tx so we make sure it has > 2 inputs without publishing it.
504504
bitcoinClient.makeFundingTx(pubkeyScript, 250 btc, FeeratePerKw(1000 sat)).pipeTo(sender.ref)
505-
val MakeFundingTxResponse(fundingTx, outputIndex, _) = sender.expectMsgType[MakeFundingTxResponse]
505+
val fundingTx = sender.expectMsgType[MakeFundingTxResponse].fundingTx
506506
assert(fundingTx.txIn.length > 2)
507507

508-
// spend the first 2 inputs
508+
// Double-spend the first 2 inputs.
509+
val amountIn = fundingTx.txIn.take(2).map(txIn => {
510+
bitcoinClient.getTransaction(txIn.outPoint.txid).pipeTo(sender.ref)
511+
sender.expectMsgType[Transaction].txOut(txIn.outPoint.index.toInt).amount
512+
}).sum
509513
val tx1 = fundingTx.copy(
510514
txIn = fundingTx.txIn.take(2),
511-
txOut = fundingTx.txOut.updated(outputIndex, fundingTx.txOut(outputIndex).copy(amount = 50 btc))
515+
txOut = Seq(TxOut(amountIn - 15_000.sat, Script.pay2wpkh(randomKey().publicKey)))
512516
)
513517
bitcoinClient.signPsbt(new Psbt(tx1), tx1.txIn.indices, Nil).pipeTo(sender.ref)
514518
val tx2 = sender.expectMsgType[ProcessPsbtResponse].finalTx_opt.toOption.get
515519
bitcoinClient.commit(tx2).pipeTo(sender.ref)
516520
sender.expectMsg(true)
517521

518-
// fundingTx inputs are still locked except for the first 2 that were just spent
522+
// The inputs of the first transaction are still locked except for the first 2 that were just spent.
519523
val expectedLocks = fundingTx.txIn.drop(2).map(_.outPoint).toSet
520524
assert(expectedLocks.nonEmpty)
521525
awaitAssert({
522526
bitcoinClient.listLockedOutpoints().pipeTo(sender.ref)
523527
sender.expectMsg(expectedLocks)
524528
}, max = 10 seconds, interval = 1 second)
525529

526-
// publishing fundingTx will fail as its first 2 inputs are already spent by tx above in the mempool
530+
// Publishing the first transaction will fail as its first 2 inputs are already spent by the second transaction.
527531
bitcoinClient.commit(fundingTx).pipeTo(sender.ref)
528532
sender.expectMsg(false)
529533

530-
// and all locked inputs should now be unlocked
534+
// And all locked inputs should now be unlocked.
531535
awaitAssert({
532536
bitcoinClient.listLockedOutpoints().pipeTo(sender.ref)
533537
sender.expectMsg(Set.empty[OutPoint])
@@ -594,15 +598,12 @@ class BitcoinCoreClientSpec extends TestKitBaseClass with BitcoindService with A
594598
assert(sender.expectMsgType[Failure].cause.getMessage.contains("Transaction not in mempool"))
595599
wallet.getMempoolTx(anchorTx2.txid).pipeTo(sender.ref)
596600
sender.expectMsgType[MempoolTx]
597-
val txNotFunded = Transaction(2, Nil, Seq(TxOut(150_000 sat, Script.pay2wpkh(priv.publicKey))), 0)
598-
wallet.fundTransaction(txNotFunded, FeeratePerKw(1000 sat), replaceable = true).pipeTo(sender.ref)
599-
assert(sender.expectMsgType[Failure].cause.getMessage.contains("Insufficient funds"))
600601

601-
// The second anchor transaction confirms, which frees up the wallet input of the first anchor transaction.
602-
generateBlocks(1)
602+
// Bitcoin Core automatically detects that the wallet input of the first anchor transaction is available again.
603603
wallet.listUnspent().pipeTo(sender.ref)
604604
val walletUtxos = sender.expectMsgType[Seq[Utxo]]
605605
assert(walletUtxos.exists(_.txid == walletInput1.txid))
606+
val txNotFunded = Transaction(2, Nil, Seq(TxOut(150_000 sat, Script.pay2wpkh(priv.publicKey))), 0)
606607
wallet.fundTransaction(txNotFunded, FeeratePerKw(1000 sat), replaceable = true).pipeTo(sender.ref)
607608
sender.expectMsgType[FundTransactionResponse]
608609
}
@@ -668,15 +669,12 @@ class BitcoinCoreClientSpec extends TestKitBaseClass with BitcoindService with A
668669
assert(sender.expectMsgType[Failure].cause.getMessage.contains("Transaction not in mempool"))
669670
miner.getMempoolTx(htlcTimeoutTx.txid).pipeTo(sender.ref)
670671
sender.expectMsgType[MempoolTx]
671-
val txNotFunded = Transaction(2, Nil, Seq(TxOut(150_000 sat, Script.pay2wpkh(priv.publicKey))), 0)
672-
wallet1.fundTransaction(txNotFunded, FeeratePerKw(1000 sat), replaceable = true).pipeTo(sender.ref)
673-
assert(sender.expectMsgType[Failure].cause.getMessage.contains("Insufficient funds"))
674672

675-
// The second anchor transaction confirms, which frees up the wallet input of the first anchor transaction.
676-
generateBlocks(1)
673+
// Bitcoin Core automatically detects that the wallet input of the first HTLC transaction is available again.
677674
wallet1.listUnspent().pipeTo(sender.ref)
678675
val walletUtxos = sender.expectMsgType[Seq[Utxo]]
679676
assert(walletUtxos.exists(_.txid == walletInput1.txid))
677+
val txNotFunded = Transaction(2, Nil, Seq(TxOut(150_000 sat, Script.pay2wpkh(priv.publicKey))), 0)
680678
wallet1.fundTransaction(txNotFunded, FeeratePerKw(1000 sat), replaceable = true).pipeTo(sender.ref)
681679
sender.expectMsgType[FundTransactionResponse]
682680
}

eclair-core/src/test/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoindService.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ trait BitcoindService extends Logging {
6262

6363
val PATH_BITCOIND = sys.env.get("BITCOIND_DIR") match {
6464
case Some(customBitcoinDir) => new File(customBitcoinDir, "bitcoind")
65-
case None => new File(TestUtils.BUILD_DIRECTORY, "bitcoin-27.2/bin/bitcoind")
65+
case None => new File(TestUtils.BUILD_DIRECTORY, "bitcoin-28.1/bin/bitcoind")
6666
}
6767
logger.info(s"using bitcoind: $PATH_BITCOIND")
6868
val PATH_BITCOIND_DATADIR = new File(INTEGRATION_TMP_DIR, "datadir-bitcoin")

0 commit comments

Comments
 (0)