diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala index cc0f65416f..47f9381453 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala @@ -86,10 +86,8 @@ case class Commitments(channelId: ByteVector32, remotePerCommitmentSecrets: ShaChain) extends AbstractCommitments { require(channelFeatures.paysDirectlyToWallet == localParams.walletStaticPaymentBasepoint.isDefined, s"localParams.walletStaticPaymentBasepoint must be defined only for commitments that pay directly to our wallet (channel features: $channelFeatures") - if (channelFeatures.hasFeature(DualFunding)) { - require(localParams.requestedChannelReserve_opt.isEmpty, "custom local channel reserve is incompatible with dual-funded channels") - require(remoteParams.requestedChannelReserve_opt.isEmpty, "custom remote channel reserve is incompatible with dual-funded channels") - } + require(channelFeatures.hasFeature(DualFunding) == localParams.requestedChannelReserve_opt.isEmpty, "custom local channel reserve is incompatible with dual-funded channels") + require(channelFeatures.hasFeature(DualFunding) == remoteParams.requestedChannelReserve_opt.isEmpty, "custom remote channel reserve is incompatible with dual-funded channels") def nextRemoteCommit_opt: Option[RemoteCommit] = remoteNextCommitInfo.swap.toOption.map(_.nextRemoteCommit) @@ -222,14 +220,14 @@ case class Commitments(channelId: ByteVector32, val localChannelReserve: Satoshi = if (channelFeatures.hasFeature(Features.DualFunding)) { (capacity / 100).max(remoteParams.dustLimit) } else { - remoteParams.requestedChannelReserve_opt.getOrElse(0 sat) + remoteParams.requestedChannelReserve_opt.get // this is guarded by a require() in Commitments } /** Channel reserve that applies to our peer's funds. */ val remoteChannelReserve: Satoshi = if (channelFeatures.hasFeature(Features.DualFunding)) { (capacity / 100).max(localParams.dustLimit) } else { - localParams.requestedChannelReserve_opt.getOrElse(0 sat) + localParams.requestedChannelReserve_opt.get // this is guarded by a require() in Commitments } // NB: when computing availableBalanceForSend and availableBalanceForReceive, the initiator keeps an extra buffer on diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala index 346a664512..5afd46c43e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala @@ -419,7 +419,7 @@ object Helpers { val reserve = if (channelFeatures.hasFeature(Features.DualFunding)) { ((localFundingAmount + remoteFundingAmount) / 100).max(localParams.dustLimit) } else { - localParams.requestedChannelReserve_opt.getOrElse(0 sat) + localParams.requestedChannelReserve_opt.get } val missing = toRemoteMsat.truncateToSatoshi - reserve - fees if (missing < Satoshi(0)) { diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunded.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunded.scala index 9deadd4034..6906cbe667 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunded.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunded.scala @@ -88,7 +88,7 @@ trait ChannelOpenSingleFunded extends SingleFundingHandlers with ErrorHandlers { pushMsat = input.pushAmount_opt.getOrElse(0 msat), dustLimitSatoshis = input.localParams.dustLimit, maxHtlcValueInFlightMsat = input.localParams.maxHtlcValueInFlightMsat, - channelReserveSatoshis = input.localParams.requestedChannelReserve_opt.getOrElse(0 sat), + channelReserveSatoshis = input.localParams.requestedChannelReserve_opt.get, htlcMinimumMsat = input.localParams.htlcMinimum, feeratePerKw = input.commitTxFeerate, toSelfDelay = input.localParams.toSelfDelay, @@ -123,7 +123,7 @@ trait ChannelOpenSingleFunded extends SingleFundingHandlers with ErrorHandlers { val accept = AcceptChannel(temporaryChannelId = open.temporaryChannelId, dustLimitSatoshis = localParams.dustLimit, maxHtlcValueInFlightMsat = localParams.maxHtlcValueInFlightMsat, - channelReserveSatoshis = localParams.requestedChannelReserve_opt.getOrElse(0 sat), + channelReserveSatoshis = localParams.requestedChannelReserve_opt.get, minimumDepth = minimumDepth.getOrElse(0), htlcMinimumMsat = localParams.htlcMinimum, toSelfDelay = localParams.toSelfDelay, diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/CommitmentsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/CommitmentsSpec.scala index c5dbb2bc60..b344aa203c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/CommitmentsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/CommitmentsSpec.scala @@ -481,8 +481,9 @@ class CommitmentsSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with object CommitmentsSpec { def makeCommitments(toLocal: MilliSatoshi, toRemote: MilliSatoshi, feeRatePerKw: FeeratePerKw = FeeratePerKw(0 sat), dustLimit: Satoshi = 0 sat, isInitiator: Boolean = true, announceChannel: Boolean = true): Commitments = { - val localParams = LocalParams(randomKey().publicKey, DeterministicWallet.KeyPath(Seq(42L)), dustLimit, UInt64.MaxValue, None, 1 msat, CltvExpiryDelta(144), 50, isInitiator, ByteVector.empty, None, Features.empty) - val remoteParams = RemoteParams(randomKey().publicKey, dustLimit, UInt64.MaxValue, None, 1 msat, CltvExpiryDelta(144), 50, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, Features.empty, None) + val channelReserve = (toLocal + toRemote).truncateToSatoshi * 0.01 + val localParams = LocalParams(randomKey().publicKey, DeterministicWallet.KeyPath(Seq(42L)), dustLimit, UInt64.MaxValue, Some(channelReserve), 1 msat, CltvExpiryDelta(144), 50, isInitiator, ByteVector.empty, None, Features.empty) + val remoteParams = RemoteParams(randomKey().publicKey, dustLimit, UInt64.MaxValue, Some(channelReserve), 1 msat, CltvExpiryDelta(144), 50, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, Features.empty, None) val commitmentInput = Funding.makeFundingInputInfo(randomBytes32(), 0, (toLocal + toRemote).truncateToSatoshi, randomKey().publicKey, remoteParams.fundingPubKey) Commitments( channelId = randomBytes32(), @@ -504,8 +505,9 @@ object CommitmentsSpec { } def makeCommitments(toLocal: MilliSatoshi, toRemote: MilliSatoshi, localNodeId: PublicKey, remoteNodeId: PublicKey, announceChannel: Boolean): Commitments = { - val localParams = LocalParams(localNodeId, DeterministicWallet.KeyPath(Seq(42L)), 0 sat, UInt64.MaxValue, None, 1 msat, CltvExpiryDelta(144), 50, isInitiator = true, ByteVector.empty, None, Features.empty) - val remoteParams = RemoteParams(remoteNodeId, 0 sat, UInt64.MaxValue, None, 1 msat, CltvExpiryDelta(144), 50, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, Features.empty, None) + val channelReserve = (toLocal + toRemote).truncateToSatoshi * 0.01 + val localParams = LocalParams(localNodeId, DeterministicWallet.KeyPath(Seq(42L)), 0 sat, UInt64.MaxValue, Some(channelReserve), 1 msat, CltvExpiryDelta(144), 50, isInitiator = true, ByteVector.empty, None, Features.empty) + val remoteParams = RemoteParams(remoteNodeId, 0 sat, UInt64.MaxValue, Some(channelReserve), 1 msat, CltvExpiryDelta(144), 50, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, randomKey().publicKey, Features.empty, None) val commitmentInput = Funding.makeFundingInputInfo(randomBytes32(), 0, (toLocal + toRemote).truncateToSatoshi, randomKey().publicKey, remoteParams.fundingPubKey) Commitments( channelId = randomBytes32(), diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentPacketSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentPacketSpec.scala index a00ca7f221..68b5b00152 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentPacketSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentPacketSpec.scala @@ -370,8 +370,9 @@ object PaymentPacketSpec { } def makeCommitments(channelId: ByteVector32, testAvailableBalanceForSend: MilliSatoshi = 50000000 msat, testAvailableBalanceForReceive: MilliSatoshi = 50000000 msat, testCapacity: Satoshi = 100000 sat, channelFeatures: ChannelFeatures = ChannelFeatures()): Commitments = { - val params = LocalParams(null, null, null, null, None, null, null, 0, isInitiator = true, null, None, null) - val remoteParams = RemoteParams(randomKey().publicKey, null, null, None, null, null, maxAcceptedHtlcs = 0, null, null, null, null, null, null, None) + val channelReserve = testCapacity * 0.01 + val params = LocalParams(null, null, null, null, Some(channelReserve), null, null, 0, isInitiator = true, null, None, null) + val remoteParams = RemoteParams(randomKey().publicKey, null, null, Some(channelReserve), null, null, maxAcceptedHtlcs = 0, null, null, null, null, null, null, None) val commitInput = InputInfo(OutPoint(randomBytes32(), 1), TxOut(testCapacity, Nil), Nil) val channelFlags = ChannelFlags.Private new Commitments(channelId, ChannelConfig.standard, channelFeatures, params, remoteParams, channelFlags, null, null, null, null, 0, 0, Map.empty, null, commitInput, null) { diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala index d8a12ffdf5..5dd9b9d3cd 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala @@ -695,7 +695,7 @@ class RouterSpec extends BaseRouterSpec { { // Private channels should also update the graph when HTLCs are relayed through them. - val balances = Set(33000000 msat, 5000000 msat) + val balances = Set(4620000 msat, 32620000 msat) val commitments = CommitmentsSpec.makeCommitments(33000000 msat, 5000000 msat, a, g, announceChannel = false) sender.send(router, AvailableBalanceChanged(sender.ref, channelId_ag_private, scids_ab, commitments)) sender.send(router, Router.GetRouterData) @@ -705,7 +705,7 @@ class RouterSpec extends BaseRouterSpec { // And the graph should be updated too. val edge_ag = data.graphWithBalances.graph.getEdge(ChannelDesc(alias_ag_private, a, g)).get assert(edge_ag.capacity == channel_ag.capacity) - assert(edge_ag.balance_opt.contains(33000000 msat)) + assert(edge_ag.balance_opt.contains(balances.last)) } }