1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-19 18:10:42 +01:00

Reject unreasonable remote dust limit (#1694)

It makes no sense to use a dust limit that's much higher than what bitcoin
mandates, so we should not allow our peer to use invalid values.
This commit is contained in:
Bastien Teinturier 2021-02-17 15:17:44 +01:00 committed by GitHub
parent 82e5b5968d
commit 3a94a80447
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 32 additions and 2 deletions

View File

@ -64,6 +64,7 @@ eclair {
channel-flags = 1 // announce channels
dust-limit-satoshis = 546
max-remote-dust-limit-satoshis = 600
max-htlc-value-in-flight-msat = 5000000000 // 50 mBTC
htlc-minimum-msat = 1
max-accepted-htlcs = 30

View File

@ -58,6 +58,7 @@ case class NodeParams(nodeKeyManager: NodeKeyManager,
syncWhitelist: Set[PublicKey],
pluginParams: Seq[PluginParams],
dustLimit: Satoshi,
maxRemoteDustLimit: Satoshi,
onChainFeeConf: OnChainFeeConf,
maxHtlcValueInFlightMsat: UInt64,
maxAcceptedHtlcs: Int,
@ -323,6 +324,7 @@ object NodeParams extends Logging {
overrideFeatures = overrideFeatures,
syncWhitelist = syncWhitelist,
dustLimit = dustLimitSatoshis,
maxRemoteDustLimit = Satoshi(config.getLong("max-remote-dust-limit-satoshis")),
onChainFeeConf = OnChainFeeConf(
feeTargets = feeTargets,
feeEstimator = feeEstimator,

View File

@ -103,6 +103,8 @@ object Helpers {
// BOLT #2: The receiving node MUST fail the channel if: it considers feerate_per_kw too small for timely processing.
if (isFeeTooSmall(open.feeratePerKw)) return Left(FeerateTooSmall(open.temporaryChannelId, open.feeratePerKw))
if (open.dustLimitSatoshis > nodeParams.maxRemoteDustLimit) return Left(DustLimitTooLarge(open.temporaryChannelId, open.dustLimitSatoshis, nodeParams.maxRemoteDustLimit))
// BOLT #2: The receiving node MUST fail the channel if: dust_limit_satoshis is greater than channel_reserve_satoshis.
if (open.dustLimitSatoshis > open.channelReserveSatoshis) return Left(DustLimitTooLarge(open.temporaryChannelId, open.dustLimitSatoshis, open.channelReserveSatoshis))
@ -140,6 +142,8 @@ object Helpers {
if (accept.dustLimitSatoshis < Channel.MIN_DUSTLIMIT) return Left(DustLimitTooSmall(accept.temporaryChannelId, accept.dustLimitSatoshis, Channel.MIN_DUSTLIMIT))
}
if (accept.dustLimitSatoshis > nodeParams.maxRemoteDustLimit) return Left(DustLimitTooLarge(open.temporaryChannelId, accept.dustLimitSatoshis, nodeParams.maxRemoteDustLimit))
// BOLT #2: The receiving node MUST fail the channel if: dust_limit_satoshis is greater than channel_reserve_satoshis.
if (accept.dustLimitSatoshis > accept.channelReserveSatoshis) return Left(DustLimitTooLarge(accept.temporaryChannelId, accept.dustLimitSatoshis, accept.channelReserveSatoshis))

View File

@ -167,6 +167,7 @@ object TestConstants {
overrideFeatures = Map.empty,
syncWhitelist = Set.empty,
dustLimit = 1100 sat,
maxRemoteDustLimit = 1500 sat,
onChainFeeConf = OnChainFeeConf(
feeTargets = FeeTargets(6, 2, 2, 6),
feeEstimator = new TestFeeEstimator,
@ -271,6 +272,7 @@ object TestConstants {
overrideFeatures = Map.empty,
syncWhitelist = Set.empty,
dustLimit = 1000 sat,
maxRemoteDustLimit = 1500 sat,
onChainFeeConf = OnChainFeeConf(
feeTargets = FeeTargets(6, 2, 2, 6),
feeEstimator = new TestFeeEstimator,

View File

@ -52,6 +52,7 @@ class WaitForAcceptChannelStateSpec extends TestKitBaseClass with FixtureAnyFunS
val aliceNodeParams = Alice.nodeParams
.modify(_.chainHash).setToIf(test.tags.contains("mainnet"))(Block.LivenetGenesisBlock.hash)
.modify(_.maxFundingSatoshis).setToIf(test.tags.contains("high-max-funding-size"))(Btc(100))
.modify(_.maxRemoteDustLimit).setToIf(test.tags.contains("high-remote-dust-limit"))(15000 sat)
val aliceParams = Alice.channelParams
.modify(_.features).setToIf(test.tags.contains("wumbo"))(Features(Set(ActivatedFeature(Wumbo, Optional))))
@ -98,7 +99,7 @@ class WaitForAcceptChannelStateSpec extends TestKitBaseClass with FixtureAnyFunS
awaitCond(alice.stateName == CLOSED)
}
test("recv AcceptChannel (invalid dust limit)", Tag("mainnet")) { f =>
test("recv AcceptChannel (dust limit too low)", Tag("mainnet")) { f =>
import f._
val accept = bob2alice.expectMsgType[AcceptChannel]
// we don't want their dust limit to be below 546
@ -109,6 +110,16 @@ class WaitForAcceptChannelStateSpec extends TestKitBaseClass with FixtureAnyFunS
awaitCond(alice.stateName == CLOSED)
}
test("recv AcceptChannel (dust limit too high)") { f =>
import f._
val accept = bob2alice.expectMsgType[AcceptChannel]
val highDustLimitSatoshis = 2000.sat
alice ! accept.copy(dustLimitSatoshis = highDustLimitSatoshis)
val error = alice2bob.expectMsgType[Error]
assert(error === Error(accept.temporaryChannelId, DustLimitTooLarge(accept.temporaryChannelId, highDustLimitSatoshis, Alice.nodeParams.maxRemoteDustLimit).getMessage))
awaitCond(alice.stateName == CLOSED)
}
test("recv AcceptChannel (to_self_delay too high)") { f =>
import f._
val accept = bob2alice.expectMsgType[AcceptChannel]
@ -151,7 +162,7 @@ class WaitForAcceptChannelStateSpec extends TestKitBaseClass with FixtureAnyFunS
awaitCond(alice.stateName == CLOSED)
}
test("recv AcceptChannel (dust limit above our reserve)") { f =>
test("recv AcceptChannel (dust limit above our reserve)", Tag("high-remote-dust-limit")) { f =>
import f._
val accept = bob2alice.expectMsgType[AcceptChannel]
val open = alice.stateData.asInstanceOf[DATA_WAIT_FOR_ACCEPT_CHANNEL].lastSent

View File

@ -188,6 +188,16 @@ class WaitForOpenChannelStateSpec extends TestKitBaseClass with FixtureAnyFunSui
awaitCond(bob.stateName == CLOSED)
}
test("recv OpenChannel (dust limit too high)") { f =>
import f._
val open = alice2bob.expectMsgType[OpenChannel]
val dustLimitTooHigh = 2000.sat
bob ! open.copy(dustLimitSatoshis = dustLimitTooHigh)
val error = bob2alice.expectMsgType[Error]
assert(error === Error(open.temporaryChannelId, DustLimitTooLarge(open.temporaryChannelId, dustLimitTooHigh, Bob.nodeParams.maxRemoteDustLimit).getMessage))
awaitCond(bob.stateName == CLOSED)
}
test("recv OpenChannel (toLocal + toRemote below reserve)") { f =>
import f._
val open = alice2bob.expectMsgType[OpenChannel]