Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Bitcoin Core to v28.x #2962

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ This means that instead of re-implementing them, Eclair benefits from the verifi

* Eclair needs a _synchronized_, _segwit-ready_, **_zeromq-enabled_**, _wallet-enabled_, _non-pruning_, _tx-indexing_ [Bitcoin Core](https://github.com/bitcoin/bitcoin) node.
* 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.
* 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.
* 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.

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

Expand Down
5 changes: 4 additions & 1 deletion docs/release-notes/eclair-vnext.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

## Major changes

<insert changes>
### Update minimal version of Bitcoin Core

With this release, eclair requires using Bitcoin Core 28.1.
Newer versions of Bitcoin Core may be used, but have not been extensively tested.

### API changes

Expand Down
18 changes: 9 additions & 9 deletions eclair-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-27.2/bitcoin-27.2-x86_64-linux-gnu.tar.gz</bitcoind.url>
<bitcoind.md5>c6dcec7ce5c43dafa48fe459911a8049</bitcoind.md5>
<bitcoind.sha1>4342a03bbcc98d81fca2c4fb404f96d5dbae4e10</bitcoind.sha1>
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-28.0/bitcoin-28.0-x86_64-linux-gnu.tar.gz</bitcoind.url>
<bitcoind.md5>2c915b5ea3a7e6662dd059d720109d7a</bitcoind.md5>
<bitcoind.sha1>e0fd253757e5f8d7d9c9cd73936e92cc6e168558</bitcoind.sha1>
</properties>
</profile>
<profile>
Expand All @@ -101,9 +101,9 @@
</os>
</activation>
<properties>
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-27.2/bitcoin-27.2-x86_64-apple-darwin.tar.gz</bitcoind.url>
<bitcoind.md5>25857522febc428160bc4eedf46eb6db</bitcoind.md5>
<bitcoind.sha1>574d753359ef2b5c1bc0ef1e028d516da86392af</bitcoind.sha1>
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-28.0/bitcoin-28.0-x86_64-apple-darwin.tar.gz</bitcoind.url>
<bitcoind.md5>d4ad664051072de807d4a864d58ccd2a</bitcoind.md5>
<bitcoind.sha1>f3e10c839a04929da870fea16829567d26dbecd8</bitcoind.sha1>
</properties>
</profile>
<profile>
Expand All @@ -114,9 +114,9 @@
</os>
</activation>
<properties>
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-27.2/bitcoin-27.2-win64.zip</bitcoind.url>
<bitcoind.md5>1a05b7880a01c0437e5e0b7e13a02635</bitcoind.md5>
<bitcoind.sha1>84c0b8d1a02d3c024881a180e8a3c670c1e0073a</bitcoind.sha1>
<bitcoind.url>https://bitcoincore.org/bin/bitcoin-core-28.0/bitcoin-28.0-win64.zip</bitcoind.url>
<bitcoind.md5>29748a873277cbb112b96c3662dcb3a4</bitcoind.md5>
<bitcoind.sha1>a7815c48d8f879f3728b50ad06a5fa1f1e10e0dc</bitcoind.sha1>
</properties>
</profile>
</profiles>
Expand Down
2 changes: 1 addition & 1 deletion eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class Setup(val datadir: File,
await(getBitcoinStatus(bitcoinClient), 30 seconds, "bitcoind did not respond after 30 seconds")
}
logger.info(s"bitcoind version=${bitcoinStatus.version}")
assert(bitcoinStatus.version >= 270200, "Eclair requires Bitcoin Core 27.2 or higher")
assert(bitcoinStatus.version >= 280000, "Eclair requires Bitcoin Core 28.x or higher")
bitcoinStatus.unspentAddresses.foreach { address =>
val isSegwit = addressToPublicKeyScript(bitcoinStatus.chainHash, address).map(script => Script.isNativeWitnessScript(script)).getOrElse(false)
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).")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,34 +500,38 @@ class BitcoinCoreClientSpec extends TestKitBaseClass with BitcoindService with A
val pubkeyScript = Script.write(Script.pay2wsh(Scripts.multiSig2of2(randomKey().publicKey, randomKey().publicKey)))
val bitcoinClient = makeBitcoinCoreClient()

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

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

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

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

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

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

// The second anchor transaction confirms, which frees up the wallet input of the first anchor transaction.
generateBlocks(1)
// Bitcoin Core automatically detects that the wallet input of the first HTLC transaction is available again.
wallet1.listUnspent().pipeTo(sender.ref)
val walletUtxos = sender.expectMsgType[Seq[Utxo]]
assert(walletUtxos.exists(_.txid == walletInput1.txid))
val txNotFunded = Transaction(2, Nil, Seq(TxOut(150_000 sat, Script.pay2wpkh(priv.publicKey))), 0)
wallet1.fundTransaction(txNotFunded, FeeratePerKw(1000 sat), replaceable = true).pipeTo(sender.ref)
sender.expectMsgType[FundTransactionResponse]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ trait BitcoindService extends Logging {

val PATH_BITCOIND = sys.env.get("BITCOIND_DIR") match {
case Some(customBitcoinDir) => new File(customBitcoinDir, "bitcoind")
case None => new File(TestUtils.BUILD_DIRECTORY, "bitcoin-27.2/bin/bitcoind")
case None => new File(TestUtils.BUILD_DIRECTORY, "bitcoin-28.0/bin/bitcoind")
}
logger.info(s"using bitcoind: $PATH_BITCOIND")
val PATH_BITCOIND_DATADIR = new File(INTEGRATION_TMP_DIR, "datadir-bitcoin")
Expand Down
Loading