From 7cc521fd2f5117593008b3f2e7c806a05ba23377 Mon Sep 17 00:00:00 2001 From: t-bast Date: Mon, 17 Jan 2022 11:27:48 +0100 Subject: [PATCH 1/2] Activate anchor outputs This feature is now ready to be widely deployed. --- docs/release-notes/eclair-vnext.md | 25 ++++++++++++++++ eclair-core/src/main/resources/reference.conf | 2 +- .../integration/ChannelIntegrationSpec.scala | 14 ++++----- .../eclair/integration/IntegrationSpec.scala | 29 +++++++++++-------- .../integration/MessageIntegrationSpec.scala | 16 +++++----- .../integration/PaymentIntegrationSpec.scala | 10 +++---- .../PerformanceIntegrationSpec.scala | 6 ++-- 7 files changed, 66 insertions(+), 36 deletions(-) diff --git a/docs/release-notes/eclair-vnext.md b/docs/release-notes/eclair-vnext.md index 6133544988..669189d987 100644 --- a/docs/release-notes/eclair-vnext.md +++ b/docs/release-notes/eclair-vnext.md @@ -4,6 +4,31 @@ ## Major changes +### Anchor outputs activated by default + +Experimental support for anchor outputs channels was first introduced in [eclair v0.4.2](https://github.com/ACINQ/eclair/releases/tag/v0.4.2). +Going from an experimental feature to production-ready required a lot more work than we expected! +What seems to be a simple change in transaction structure had a lot of impact in many unexpected places, and fundamentally changes the mechanisms to ensure funds safety. + +When using anchor outputs, you will need to keep utxos available in your `bitcoind` wallet to fee-bump HTLC transactions when channels are force-closed. +Eclair will warn you via the `notifications.log` file when your `bitcoind` wallet balance is too low to protect your funds against malicious channel peers. + +We recommend activating debug logs for the transaction publication mechanisms. +This will make it much easier to follow the trail of RBF-ed transactions, and shouldn't be too noisy unless you constantly have a lot of channels force-closing. +To activate these logs, simply add the following line to your `logback.xml`: + +```xml + +``` + +You don't even need to restart eclair, it will automatically pick up the logging configuration update after a short while. + +If you don't want to use anchor outputs, you can disable the feature in your `eclair.conf`: + +```conf +eclair.features.option_anchors_zero_fee_htlc_tx = disabled +``` + ### Alternate strategy to avoid mass force-close of channels in certain cases The default strategy, when an unhandled exception or internal error happens, is to locally force-close the channel. Not only is there a delay before the channel balance gets refunded, but if the exception was due to some misconfiguration or bug in eclair that affects all channels, we risk force-closing all channels. diff --git a/eclair-core/src/main/resources/reference.conf b/eclair-core/src/main/resources/reference.conf index ee3274907e..32f4447418 100644 --- a/eclair-core/src/main/resources/reference.conf +++ b/eclair-core/src/main/resources/reference.conf @@ -54,7 +54,7 @@ eclair { // NB: option_anchors_zero_fee_htlc_tx should always be preferred to option_anchor_outputs (it's safer). // Do not enable option_anchor_outputs unless you really know what you're doing. option_anchor_outputs = disabled - option_anchors_zero_fee_htlc_tx = disabled + option_anchors_zero_fee_htlc_tx = optional option_shutdown_anysegwit = optional option_onion_messages = optional option_channel_type = optional diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala index 4b343da235..2c57316742 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala @@ -457,9 +457,9 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec { class StandardChannelIntegrationSpec extends ChannelIntegrationSpec { test("start eclair nodes") { - instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29740, "eclair.api.port" -> 28090).asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29741, "eclair.api.port" -> 28091).asJava).withFallback(withAnchorOutputs).withFallback(withWumbo).withFallback(commonConfig)) - instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29742, "eclair.api.port" -> 28092).asJava).withFallback(withWumbo).withFallback(commonConfig)) + instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29740, "eclair.api.port" -> 28090).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig)) + instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29741, "eclair.api.port" -> 28091).asJava).withFallback(withAnchorOutputs).withFallback(commonConfig)) + instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29742, "eclair.api.port" -> 28092).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig)) } test("connect nodes") { @@ -785,8 +785,8 @@ class AnchorOutputChannelIntegrationSpec extends AnchorChannelIntegrationSpec { override val commitmentFormat = Transactions.UnsafeLegacyAnchorOutputsCommitmentFormat test("start eclair nodes") { - instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29750, "eclair.api.port" -> 28093).asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29751, "eclair.api.port" -> 28094).asJava).withFallback(withAnchorOutputs).withFallback(withWumbo).withFallback(commonConfig)) + instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29750, "eclair.api.port" -> 28093).asJava).withFallback(withStaticRemoteKey).withFallback(commonConfig)) + instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29751, "eclair.api.port" -> 28094).asJava).withFallback(withAnchorOutputs).withFallback(commonConfig)) instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29753, "eclair.api.port" -> 28095).asJava).withFallback(withAnchorOutputs).withFallback(commonConfig)) } @@ -825,8 +825,8 @@ class AnchorOutputZeroFeeHtlcTxsChannelIntegrationSpec extends AnchorChannelInte override val commitmentFormat = Transactions.ZeroFeeHtlcTxAnchorOutputsCommitmentFormat test("start eclair nodes") { - instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29760, "eclair.api.port" -> 28096).asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29761, "eclair.api.port" -> 28097).asJava).withFallback(withAnchorOutputsZeroFeeHtlcTxs).withFallback(withWumbo).withFallback(commonConfig)) + instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29760, "eclair.api.port" -> 28096).asJava).withFallback(withStaticRemoteKey).withFallback(commonConfig)) + instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29761, "eclair.api.port" -> 28097).asJava).withFallback(withAnchorOutputsZeroFeeHtlcTxs).withFallback(commonConfig)) instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.expiry-delta-blocks" -> 40, "eclair.fulfill-safety-before-timeout-blocks" -> 12, "eclair.server.port" -> 29763, "eclair.api.port" -> 28098).asJava).withFallback(withAnchorOutputsZeroFeeHtlcTxs).withFallback(commonConfig)) } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala index 582f1bf331..20adb004b7 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala @@ -87,33 +87,38 @@ abstract class IntegrationSpec extends TestKitBaseClass with BitcoindService wit "eclair.router.broadcast-interval" -> "2 seconds", "eclair.auto-reconnect" -> false, "eclair.to-remote-delay-blocks" -> 24, - "eclair.multi-part-payment-expiry" -> "20 seconds").asJava).withFallback(ConfigFactory.load()) + "eclair.multi-part-payment-expiry" -> "20 seconds", + "eclair.max-funding-satoshis" -> 500000000).asJava).withFallback(ConfigFactory.load()) - val commonFeatures = ConfigFactory.parseMap(Map( + private val commonFeatures = ConfigFactory.parseMap(Map( s"eclair.features.${OptionDataLossProtect.rfcName}" -> "optional", s"eclair.features.${ChannelRangeQueries.rfcName}" -> "optional", s"eclair.features.${ChannelRangeQueriesExtended.rfcName}" -> "optional", s"eclair.features.${VariableLengthOnion.rfcName}" -> "mandatory", s"eclair.features.${PaymentSecret.rfcName}" -> "mandatory", - s"eclair.features.${BasicMultiPartPayment.rfcName}" -> "optional" + s"eclair.features.${BasicMultiPartPayment.rfcName}" -> "optional", + s"eclair.features.${Wumbo.rfcName}" -> "optional", + s"eclair.features.${ShutdownAnySegwit.rfcName}" -> "optional", + s"eclair.features.${ChannelType.rfcName}" -> "optional", ).asJava) - val withWumbo = commonFeatures.withFallback(ConfigFactory.parseMap(Map( - s"eclair.features.${Wumbo.rfcName}" -> "optional", - "eclair.max-funding-satoshis" -> 500000000 + val withDefaultCommitment = commonFeatures.withFallback(ConfigFactory.parseMap(Map( + s"eclair.features.${StaticRemoteKey.rfcName}" -> "disabled", + s"eclair.features.${AnchorOutputs.rfcName}" -> "disabled", + s"eclair.features.${AnchorOutputsZeroFeeHtlcTx.rfcName}" -> "disabled", ).asJava)) - val withStaticRemoteKey = commonFeatures.withFallback(ConfigFactory.parseMap(Map( + val withStaticRemoteKey = ConfigFactory.parseMap(Map( s"eclair.features.${StaticRemoteKey.rfcName}" -> "optional" - ).asJava)) + ).asJava).withFallback(withDefaultCommitment) - val withAnchorOutputs = withStaticRemoteKey.withFallback(ConfigFactory.parseMap(Map( + val withAnchorOutputs = ConfigFactory.parseMap(Map( s"eclair.features.${AnchorOutputs.rfcName}" -> "optional" - ).asJava)) + ).asJava).withFallback(withStaticRemoteKey) - val withAnchorOutputsZeroFeeHtlcTxs = withAnchorOutputs.withFallback(ConfigFactory.parseMap(Map( + val withAnchorOutputsZeroFeeHtlcTxs = ConfigFactory.parseMap(Map( s"eclair.features.${AnchorOutputsZeroFeeHtlcTx.rfcName}" -> "optional" - ).asJava)) + ).asJava).withFallback(withStaticRemoteKey) implicit val formats: Formats = DefaultFormats diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/MessageIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/MessageIntegrationSpec.scala index 8b6860737d..6dd4603ec3 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/MessageIntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/MessageIntegrationSpec.scala @@ -42,12 +42,12 @@ class MessageIntegrationSpec extends IntegrationSpec { implicit val timeout: Timeout = FiniteDuration(30, SECONDS) test("start eclair nodes") { - instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.server.port" -> 30700, "eclair.api.port" -> 30780, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "relay-all", "eclair.onion-messages.reply-timeout" -> "1 minute").asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("B", ConfigFactory.parseMap(Map("eclair.node-alias" -> "B", "eclair.server.port" -> 30701, "eclair.api.port" -> 30781, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "relay-all", "eclair.onion-messages.reply-timeout" -> "1 second").asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.server.port" -> 30702, "eclair.api.port" -> 30782, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "relay-all").asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("D", ConfigFactory.parseMap(Map("eclair.node-alias" -> "D", "eclair.server.port" -> 30703, "eclair.api.port" -> 30783).asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("E", ConfigFactory.parseMap(Map("eclair.node-alias" -> "E", "eclair.server.port" -> 30704, "eclair.api.port" -> 30784, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "channels-only").asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.server.port" -> 30705, "eclair.api.port" -> 30785, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "no-relay").asJava).withFallback(commonFeatures).withFallback(commonConfig)) + instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.server.port" -> 30700, "eclair.api.port" -> 30780, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "relay-all", "eclair.onion-messages.reply-timeout" -> "1 minute").asJava).withFallback(commonConfig)) + instantiateEclairNode("B", ConfigFactory.parseMap(Map("eclair.node-alias" -> "B", "eclair.server.port" -> 30701, "eclair.api.port" -> 30781, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "relay-all", "eclair.onion-messages.reply-timeout" -> "1 second").asJava).withFallback(commonConfig)) + instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.server.port" -> 30702, "eclair.api.port" -> 30782, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "relay-all").asJava).withFallback(commonConfig)) + instantiateEclairNode("D", ConfigFactory.parseMap(Map("eclair.node-alias" -> "D", "eclair.server.port" -> 30703, "eclair.api.port" -> 30783).asJava).withFallback(commonConfig)) + instantiateEclairNode("E", ConfigFactory.parseMap(Map("eclair.node-alias" -> "E", "eclair.server.port" -> 30704, "eclair.api.port" -> 30784, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "channels-only").asJava).withFallback(commonConfig)) + instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.server.port" -> 30705, "eclair.api.port" -> 30785, s"eclair.features.${Features.OnionMessages.rfcName}" -> "optional", "eclair.onion-messages.relay-policy" -> "no-relay").asJava).withFallback(commonConfig)) } test("try to reach unknown node") { @@ -226,7 +226,7 @@ class MessageIntegrationSpec extends IntegrationSpec { val probe = TestProbe() val eventListener = TestProbe() nodes("C").system.eventStream.subscribe(eventListener.ref, classOf[OnionMessages.ReceiveMessage]) - alice.sendOnionMessage(nodes("E").nodeParams.nodeId :: Nil, Left( nodes("C").nodeParams.nodeId), None, hex"710301020375020102").pipeTo(probe.ref) + alice.sendOnionMessage(nodes("E").nodeParams.nodeId :: Nil, Left(nodes("C").nodeParams.nodeId), None, hex"710301020375020102").pipeTo(probe.ref) assert(probe.expectMsgType[SendOnionMessageResponse].sent) val r = eventListener.expectMsgType[OnionMessages.ReceiveMessage](max = 60 seconds) @@ -302,7 +302,7 @@ class MessageIntegrationSpec extends IntegrationSpec { val probe = TestProbe() val eventListener = TestProbe() nodes("C").system.eventStream.subscribe(eventListener.ref, classOf[OnionMessages.ReceiveMessage]) - alice.sendOnionMessage(nodes("B").nodeParams.nodeId :: Nil, Left( nodes("C").nodeParams.nodeId), None, hex"7300").pipeTo(probe.ref) + alice.sendOnionMessage(nodes("B").nodeParams.nodeId :: Nil, Left(nodes("C").nodeParams.nodeId), None, hex"7300").pipeTo(probe.ref) assert(probe.expectMsgType[SendOnionMessageResponse].sent) val r = eventListener.expectMsgType[OnionMessages.ReceiveMessage](max = 60 seconds) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala index a5f944d07a..5c5cadc106 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala @@ -59,12 +59,12 @@ import scala.jdk.CollectionConverters._ class PaymentIntegrationSpec extends IntegrationSpec { test("start eclair nodes") { - instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 130, "eclair.server.port" -> 29730, "eclair.api.port" -> 28080, "eclair.channel-flags" -> 0).asJava).withFallback(commonFeatures).withFallback(commonConfig)) // A's channels are private - instantiateEclairNode("B", ConfigFactory.parseMap(Map("eclair.node-alias" -> "B", "eclair.expiry-delta-blocks" -> 131, "eclair.server.port" -> 29731, "eclair.api.port" -> 28081, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(commonFeatures).withFallback(commonConfig)) - instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 132, "eclair.server.port" -> 29732, "eclair.api.port" -> 28082, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(withAnchorOutputsZeroFeeHtlcTxs).withFallback(withWumbo).withFallback(commonConfig)) - instantiateEclairNode("D", ConfigFactory.parseMap(Map("eclair.node-alias" -> "D", "eclair.expiry-delta-blocks" -> 133, "eclair.server.port" -> 29733, "eclair.api.port" -> 28083, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(commonFeatures).withFallback(commonConfig)) + instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.expiry-delta-blocks" -> 130, "eclair.server.port" -> 29730, "eclair.api.port" -> 28080, "eclair.channel-flags" -> 0).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig)) // A's channels are private + instantiateEclairNode("B", ConfigFactory.parseMap(Map("eclair.node-alias" -> "B", "eclair.expiry-delta-blocks" -> 131, "eclair.server.port" -> 29731, "eclair.api.port" -> 28081, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig)) + instantiateEclairNode("C", ConfigFactory.parseMap(Map("eclair.node-alias" -> "C", "eclair.expiry-delta-blocks" -> 132, "eclair.server.port" -> 29732, "eclair.api.port" -> 28082, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(withAnchorOutputsZeroFeeHtlcTxs).withFallback(commonConfig)) + instantiateEclairNode("D", ConfigFactory.parseMap(Map("eclair.node-alias" -> "D", "eclair.expiry-delta-blocks" -> 133, "eclair.server.port" -> 29733, "eclair.api.port" -> 28083, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(withDefaultCommitment).withFallback(commonConfig)) instantiateEclairNode("E", ConfigFactory.parseMap(Map("eclair.node-alias" -> "E", "eclair.expiry-delta-blocks" -> 134, "eclair.server.port" -> 29734, "eclair.api.port" -> 28084).asJava).withFallback(withAnchorOutputsZeroFeeHtlcTxs).withFallback(commonConfig)) - instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.expiry-delta-blocks" -> 135, "eclair.server.port" -> 29735, "eclair.api.port" -> 28085, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(withWumbo).withFallback(commonConfig)) + instantiateEclairNode("F", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F", "eclair.expiry-delta-blocks" -> 135, "eclair.server.port" -> 29735, "eclair.api.port" -> 28085, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(commonConfig)) instantiateEclairNode("G", ConfigFactory.parseMap(Map("eclair.node-alias" -> "G", "eclair.expiry-delta-blocks" -> 136, "eclair.server.port" -> 29736, "eclair.api.port" -> 28086, "eclair.relay.fees.public-channels.fee-base-msat" -> 1010, "eclair.relay.fees.public-channels.fee-proportional-millionths" -> 102, "eclair.trampoline-payments-enable" -> true).asJava).withFallback(commonConfig)) } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/PerformanceIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/PerformanceIntegrationSpec.scala index 9097df797c..2951239564 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/PerformanceIntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/PerformanceIntegrationSpec.scala @@ -19,13 +19,13 @@ package fr.acinq.eclair.integration import akka.testkit.TestProbe import com.typesafe.config.ConfigFactory import fr.acinq.bitcoin.SatoshiLong -import fr.acinq.eclair.{MilliSatoshiLong, TimestampMilli} import fr.acinq.eclair.channel._ import fr.acinq.eclair.payment._ import fr.acinq.eclair.payment.receive.MultiPartHandler.ReceivePayment import fr.acinq.eclair.payment.send.MultiPartPaymentLifecycle.PreimageReceived import fr.acinq.eclair.payment.send.PaymentInitiator import fr.acinq.eclair.router.Router +import fr.acinq.eclair.{MilliSatoshiLong, TimestampMilli} import org.scalatest.Ignore import java.util.UUID @@ -48,8 +48,8 @@ class PerformanceIntegrationSpec extends IntegrationSpec { "eclair.file-backup.enabled" -> false, ).asJava) - instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.server.port" -> 29730).asJava).withFallback(commonPerfTestConfig).withFallback(commonFeatures).withFallback(commonConfig)) // A's channels are private - instantiateEclairNode("B", ConfigFactory.parseMap(Map("eclair.node-alias" -> "B", "eclair.server.port" -> 29731).asJava).withFallback(commonPerfTestConfig).withFallback(commonFeatures).withFallback(commonConfig)) + instantiateEclairNode("A", ConfigFactory.parseMap(Map("eclair.node-alias" -> "A", "eclair.server.port" -> 29730).asJava).withFallback(commonPerfTestConfig).withFallback(commonConfig)) // A's channels are private + instantiateEclairNode("B", ConfigFactory.parseMap(Map("eclair.node-alias" -> "B", "eclair.server.port" -> 29731).asJava).withFallback(commonPerfTestConfig).withFallback(commonConfig)) } test("connect nodes") { From 07da8abdb4d4c124eff134c0347676adc80ff48c Mon Sep 17 00:00:00 2001 From: t-bast Date: Wed, 19 Jan 2022 11:35:22 +0100 Subject: [PATCH 2/2] fixup! Activate anchor outputs --- docs/release-notes/eclair-vnext.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/eclair-vnext.md b/docs/release-notes/eclair-vnext.md index 669189d987..e7319f82e3 100644 --- a/docs/release-notes/eclair-vnext.md +++ b/docs/release-notes/eclair-vnext.md @@ -12,6 +12,7 @@ What seems to be a simple change in transaction structure had a lot of impact in When using anchor outputs, you will need to keep utxos available in your `bitcoind` wallet to fee-bump HTLC transactions when channels are force-closed. Eclair will warn you via the `notifications.log` file when your `bitcoind` wallet balance is too low to protect your funds against malicious channel peers. +Eclair will wait for you to add funds to your wallet and automatically retry, but you may be at risk in the meantime if you had pending payments at the time of the force-close. We recommend activating debug logs for the transaction publication mechanisms. This will make it much easier to follow the trail of RBF-ed transactions, and shouldn't be too noisy unless you constantly have a lot of channels force-closing.