diff --git a/eclair-core/src/main/resources/reference.conf b/eclair-core/src/main/resources/reference.conf index 6b1622185b..c96c174efd 100644 --- a/eclair-core/src/main/resources/reference.conf +++ b/eclair-core/src/main/resources/reference.conf @@ -287,7 +287,7 @@ eclair { autoprobe-count = 0 // number of parallel tasks that send test payments to detect invalid channels router { - watch-spent-window = 1 minute // at startup watches will be put back within that window to reduce herd effect; must be > 0s + watch-spent-window = 60 minutes // at startup watches on public channels will be put back within that window to reduce herd effect; must be > 0s channel-exclude-duration = 60 seconds // when a temporary channel failure is returned, we exclude the channel from our payment routes for this duration broadcast-interval = 60 seconds // see BOLT #7 diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala index c2dc4b999c..74899f1388 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala @@ -370,8 +370,11 @@ class PeerConnection(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: A } else if (d.behavior.fundingTxAlreadySpentCount < MAX_FUNDING_TX_ALREADY_SPENT) { d.behavior.copy(fundingTxAlreadySpentCount = d.behavior.fundingTxAlreadySpentCount + 1) } else { + // Our peer isn't necessarily malicious: their bitcoind node may be late, or they restarted and have not + // yet received notifications for the recently closed channels. There may also be splicing attempts that + // are being confirmed and look like closed channels, but actually aren't. + // But we still need to protect ourselves against potentially malicious peers and ignore them. log.warning(s"peer sent us too many channel announcements with funding tx already spent (count=${d.behavior.fundingTxAlreadySpentCount + 1}), ignoring network announcements for $IGNORE_NETWORK_ANNOUNCEMENTS_PERIOD") - d.transport ! Warning("too many channel announcements with funding tx already spent, please check your bitcoin node") startSingleTimer(ResumeAnnouncements.toString, ResumeAnnouncements, IGNORE_NETWORK_ANNOUNCEMENTS_PERIOD) d.behavior.copy(fundingTxAlreadySpentCount = d.behavior.fundingTxAlreadySpentCount + 1, ignoreNetworkAnnouncement = true) } @@ -529,10 +532,7 @@ object PeerConnection { // @formatter:on val IGNORE_NETWORK_ANNOUNCEMENTS_PERIOD: FiniteDuration = 5 minutes - - // @formatter:off - val MAX_FUNDING_TX_ALREADY_SPENT = 10 - // @formatter:on + val MAX_FUNDING_TX_ALREADY_SPENT = 250 def props(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef): Props = Props(new PeerConnection(keyPair, conf, switchboard, router)) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala index 9989b9ac71..aa5fab6cff 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala @@ -338,6 +338,10 @@ class PeerConnectionSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wi val probe = TestProbe() connect(nodeParams, remoteNodeId, switchboard, router, connection, transport, peerConnection, peer) + val fakeRoutingInfo = RoutingSyncSpec.shortChannelIds.take(PeerConnection.MAX_FUNDING_TX_ALREADY_SPENT + 1).toSeq.map(RoutingSyncSpec.makeFakeRoutingInfo(pub2priv)) + val channels = fakeRoutingInfo.map(_._1.ann) + val updates = fakeRoutingInfo.flatMap(_._1.update_1_opt) ++ fakeRoutingInfo.flatMap(_._1.update_2_opt) + val query = QueryShortChannelIds( Alice.nodeParams.chainHash, EncodedShortChannelIds(EncodingType.UNCOMPRESSED, List(RealShortChannelId(42000))), @@ -355,13 +359,8 @@ class PeerConnectionSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wi router.send(peerConnection, GossipDecision.ChannelClosed(c)) } // peer will temporary ignore announcements coming from bob - var warningSent = false for (ann <- channels ++ updates) { transport.send(peerConnection, ann) - if (!warningSent) { - transport.expectMsgType[Warning] - warningSent = true - } transport.expectMsg(TransportHandler.ReadAck(ann)) } router.expectNoMessage(1 second)