Skip to content

Commit 2e6c6fe

Browse files
authored
Use Uint64 for max_htlc_value_in_flight_msat consistently (#3113)
The `max_htlc_value_in_flight_msat` field in the `open_channel` and `accept_channel` messages is encoded as a `uint64`, while our internal class for `MilliSatoshi` amounts uses a `Long`. This forced us to store the remote value as a `UInt64` while our local value was `MilliSatoshi`, which was inconsistent. We fix this inconsistency by using an `UInt64` for both the local and remote values. Since `MilliSatoshi` amounts were already encoded using 64 bits, we can simply switch the codec and we'll be able to start storing amounts larger than 2^63. When considering actual HTLC amounts, we can safely round this down to a `MilliSatoshi` value though, which is useful for channel updates where the spec disallows setting a value larger than the channel capacity, where we thus use the `MilliSatoshi` class.
1 parent 961f844 commit 2e6c6fe

27 files changed

+106
-91
lines changed

eclair-core/src/main/scala/fr/acinq/eclair/MilliSatoshi.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package fr.acinq.eclair
1818

19-
import fr.acinq.bitcoin.scalacompat.{Btc, BtcAmount, MilliBtc, Satoshi, btc2satoshi, millibtc2satoshi}
19+
import fr.acinq.bitcoin.scalacompat.{Btc, BtcAmount, BtcDouble, MilliBtc, Satoshi, btc2satoshi, millibtc2satoshi}
2020

2121
/**
2222
* Created by t-bast on 22/08/2019.
@@ -60,6 +60,8 @@ case class MilliSatoshi(private val underlying: Long) extends Ordered[MilliSatos
6060

6161
object MilliSatoshi {
6262

63+
val MaxMoney: MilliSatoshi = toMilliSatoshi(21e6.btc)
64+
6365
private def satoshi2millisatoshi(input: Satoshi): MilliSatoshi = MilliSatoshi(input.toLong * 1000L)
6466

6567
def toMilliSatoshi(amount: BtcAmount): MilliSatoshi = amount match {

eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ final case class DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT(commitments: Com
664664
case class LocalParams(nodeId: PublicKey,
665665
fundingKeyPath: DeterministicWallet.KeyPath,
666666
dustLimit: Satoshi,
667-
maxHtlcValueInFlightMsat: MilliSatoshi,
667+
maxHtlcValueInFlightMsat: UInt64,
668668
initialRequestedChannelReserve_opt: Option[Satoshi],
669669
htlcMinimum: MilliSatoshi,
670670
toSelfDelay: CltvExpiryDelta,
@@ -684,7 +684,7 @@ case class LocalParams(nodeId: PublicKey,
684684
*/
685685
case class RemoteParams(nodeId: PublicKey,
686686
dustLimit: Satoshi,
687-
maxHtlcValueInFlightMsat: UInt64, // this is not MilliSatoshi because it can exceed the total amount of MilliSatoshi
687+
maxHtlcValueInFlightMsat: UInt64,
688688
initialRequestedChannelReserve_opt: Option[Satoshi],
689689
htlcMinimum: MilliSatoshi,
690690
toSelfDelay: CltvExpiryDelta,

eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelExceptions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ case class UnexpectedHtlcId (override val channelId: Byte
128128
case class ExpiryTooSmall (override val channelId: ByteVector32, minimum: CltvExpiry, actual: CltvExpiry, blockHeight: BlockHeight) extends ChannelException(channelId, s"expiry too small: minimum=$minimum actual=$actual blockHeight=$blockHeight")
129129
case class ExpiryTooBig (override val channelId: ByteVector32, maximum: CltvExpiry, actual: CltvExpiry, blockHeight: BlockHeight) extends ChannelException(channelId, s"expiry too big: maximum=$maximum actual=$actual blockHeight=$blockHeight")
130130
case class HtlcValueTooSmall (override val channelId: ByteVector32, minimum: MilliSatoshi, actual: MilliSatoshi) extends ChannelException(channelId, s"htlc value too small: minimum=$minimum actual=$actual")
131-
case class HtlcValueTooHighInFlight (override val channelId: ByteVector32, maximum: MilliSatoshi, actual: MilliSatoshi) extends ChannelException(channelId, s"in-flight htlcs hold too much value: maximum=$maximum actual=$actual")
131+
case class HtlcValueTooHighInFlight (override val channelId: ByteVector32, maximum: UInt64, actual: MilliSatoshi) extends ChannelException(channelId, s"in-flight htlcs hold too much value: maximum=${maximum.toBigInt} msat actual=$actual")
132132
case class TooManyAcceptedHtlcs (override val channelId: ByteVector32, maximum: Long) extends ChannelException(channelId, s"too many accepted htlcs: maximum=$maximum")
133133
case class LocalDustHtlcExposureTooHigh (override val channelId: ByteVector32, maximum: Satoshi, actual: MilliSatoshi) extends ChannelException(channelId, s"dust htlcs hold too much value: maximum=$maximum actual=$actual")
134134
case class RemoteDustHtlcExposureTooHigh (override val channelId: ByteVector32, maximum: Satoshi, actual: MilliSatoshi) extends ChannelException(channelId, s"dust htlcs hold too much value: maximum=$maximum actual=$actual")

eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import fr.acinq.eclair.router.Announcements
1515
import fr.acinq.eclair.transactions.Transactions._
1616
import fr.acinq.eclair.transactions._
1717
import fr.acinq.eclair.wire.protocol._
18-
import fr.acinq.eclair.{BlockHeight, CltvExpiry, CltvExpiryDelta, Feature, Features, MilliSatoshi, MilliSatoshiLong, NodeParams, RealShortChannelId, payment}
18+
import fr.acinq.eclair.{BlockHeight, CltvExpiry, CltvExpiryDelta, Feature, Features, MilliSatoshi, MilliSatoshiLong, NodeParams, RealShortChannelId, UInt64, payment}
1919
import scodec.bits.ByteVector
2020

2121
/** Static channel parameters shared by all commitments. */
@@ -36,7 +36,7 @@ case class ChannelParams(channelId: ByteVector32,
3636
val remoteNodeId: PublicKey = remoteParams.nodeId
3737

3838
// We can safely cast to millisatoshis since we verify that it's less than a valid millisatoshi amount.
39-
val maxHtlcAmount: MilliSatoshi = remoteParams.maxHtlcValueInFlightMsat.toBigInt.min(localParams.maxHtlcValueInFlightMsat.toLong).toLong.msat
39+
val maxHtlcAmount: MilliSatoshi = Seq(localParams.maxHtlcValueInFlightMsat, remoteParams.maxHtlcValueInFlightMsat, UInt64(MilliSatoshi.MaxMoney.toLong)).min.toBigInt.toLong.msat
4040

4141
// If we've set the 0-conf feature bit for this peer, we will always use 0-conf with them.
4242
val zeroConf: Boolean = localParams.initFeatures.hasFeature(Features.ZeroConf)
@@ -505,7 +505,7 @@ case class Commitment(fundingTxIndex: Long,
505505
// We apply local *and* remote restrictions, to ensure both peers are happy with the resulting number of HTLCs.
506506
// NB: we need the `toSeq` because otherwise duplicate amountMsat would be removed (since outgoingHtlcs is a Set).
507507
val htlcValueInFlight = outgoingHtlcs.toSeq.map(_.amountMsat).sum
508-
val allowedHtlcValueInFlight = params.maxHtlcAmount
508+
val allowedHtlcValueInFlight = UInt64(params.maxHtlcAmount.toLong)
509509
if (allowedHtlcValueInFlight < htlcValueInFlight) {
510510
return Left(HtlcValueTooHighInFlight(params.channelId, maximum = allowedHtlcValueInFlight, actual = htlcValueInFlight))
511511
}

eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,18 @@ object Channel {
112112
require(balanceThresholds.sortBy(_.available) == balanceThresholds, "channel-update.balance-thresholds must be sorted by available-sat")
113113

114114
def minFundingSatoshis(flags: ChannelFlags): Satoshi = if (flags.announceChannel) minFundingPublicSatoshis else minFundingPrivateSatoshis
115+
116+
def maxHtlcValueInFlight(fundingAmount: Satoshi, unlimited: Boolean): UInt64 = {
117+
if (unlimited) {
118+
// We don't want to impose limits on the amount in flight, typically to allow fully emptying the channel.
119+
UInt64.MaxValue
120+
} else {
121+
// NB: when we're the initiator, we don't know yet if the remote peer will contribute to the funding amount, so
122+
// the percentage-based value may be underestimated. That's ok, this is a security parameter so it makes sense to
123+
// base it on the amount that we're contributing instead of the total funding amount.
124+
UInt64(maxHtlcValueInFlightMsat.min(fundingAmount * maxHtlcValueInFlightPercent / 100).toLong)
125+
}
126+
}
115127
}
116128

117129
trait TxPublisherFactory {

eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenDualFunded.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import fr.acinq.eclair.channel.publish.TxPublisher.SetChannelId
2828
import fr.acinq.eclair.crypto.ShaChain
2929
import fr.acinq.eclair.io.Peer.{LiquidityPurchaseSigned, OpenChannelResponse}
3030
import fr.acinq.eclair.wire.protocol._
31-
import fr.acinq.eclair.{ToMilliSatoshiConversion, UInt64, randomBytes32}
31+
import fr.acinq.eclair.{ToMilliSatoshiConversion, randomBytes32}
3232

3333
/**
3434
* Created by t-bast on 19/04/2022.
@@ -120,7 +120,7 @@ trait ChannelOpenDualFunded extends DualFundingHandlers with ErrorHandlers {
120120
commitmentFeerate = input.commitTxFeerate,
121121
fundingAmount = input.fundingAmount,
122122
dustLimit = input.localParams.dustLimit,
123-
maxHtlcValueInFlightMsat = UInt64(input.localParams.maxHtlcValueInFlightMsat.toLong),
123+
maxHtlcValueInFlightMsat = input.localParams.maxHtlcValueInFlightMsat,
124124
htlcMinimum = input.localParams.htlcMinimum,
125125
toSelfDelay = input.localParams.toSelfDelay,
126126
maxAcceptedHtlcs = input.localParams.maxAcceptedHtlcs,
@@ -179,7 +179,7 @@ trait ChannelOpenDualFunded extends DualFundingHandlers with ErrorHandlers {
179179
temporaryChannelId = open.temporaryChannelId,
180180
fundingAmount = localAmount,
181181
dustLimit = localParams.dustLimit,
182-
maxHtlcValueInFlightMsat = UInt64(localParams.maxHtlcValueInFlightMsat.toLong),
182+
maxHtlcValueInFlightMsat = localParams.maxHtlcValueInFlightMsat,
183183
htlcMinimum = localParams.htlcMinimum,
184184
minimumDepth = minDepth_opt.getOrElse(0).toLong,
185185
toSelfDelay = localParams.toSelfDelay,

eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunded.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import fr.acinq.eclair.io.Peer.OpenChannelResponse
3333
import fr.acinq.eclair.transactions.Scripts
3434
import fr.acinq.eclair.transactions.Transactions.{SegwitV0CommitmentFormat, SimpleTaprootChannelCommitmentFormat}
3535
import fr.acinq.eclair.wire.protocol.{AcceptChannel, AnnouncementSignatures, ChannelReady, ChannelTlv, Error, FundingCreated, FundingSigned, OpenChannel, TlvStream}
36-
import fr.acinq.eclair.{MilliSatoshiLong, UInt64, randomKey, toLongId}
36+
import fr.acinq.eclair.{MilliSatoshiLong, randomKey, toLongId}
3737
import scodec.bits.ByteVector
3838

3939
/**
@@ -82,7 +82,7 @@ trait ChannelOpenSingleFunded extends SingleFundingHandlers with ErrorHandlers {
8282
fundingSatoshis = input.fundingAmount,
8383
pushMsat = input.pushAmount_opt.getOrElse(0 msat),
8484
dustLimitSatoshis = input.localParams.dustLimit,
85-
maxHtlcValueInFlightMsat = UInt64(input.localParams.maxHtlcValueInFlightMsat.toLong),
85+
maxHtlcValueInFlightMsat = input.localParams.maxHtlcValueInFlightMsat,
8686
channelReserveSatoshis = input.localParams.initialRequestedChannelReserve_opt.get,
8787
htlcMinimumMsat = input.localParams.htlcMinimum,
8888
feeratePerKw = input.commitTxFeerate,
@@ -132,7 +132,7 @@ trait ChannelOpenSingleFunded extends SingleFundingHandlers with ErrorHandlers {
132132
val localShutdownScript = d.initFundee.localParams.upfrontShutdownScript_opt.getOrElse(ByteVector.empty)
133133
val accept = AcceptChannel(temporaryChannelId = open.temporaryChannelId,
134134
dustLimitSatoshis = d.initFundee.localParams.dustLimit,
135-
maxHtlcValueInFlightMsat = UInt64(d.initFundee.localParams.maxHtlcValueInFlightMsat.toLong),
135+
maxHtlcValueInFlightMsat = d.initFundee.localParams.maxHtlcValueInFlightMsat,
136136
channelReserveSatoshis = d.initFundee.localParams.initialRequestedChannelReserve_opt.get,
137137
minimumDepth = minimumDepth.getOrElse(0).toLong,
138138
htlcMinimumMsat = d.initFundee.localParams.htlcMinimum,

eclair-core/src/main/scala/fr/acinq/eclair/io/OpenChannelInterceptor.scala

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import akka.actor.typed.scaladsl.adapter.TypedActorRefOps
2222
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
2323
import akka.actor.typed.{ActorRef, Behavior}
2424
import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
25-
import fr.acinq.bitcoin.scalacompat.{BtcDouble, ByteVector32, Satoshi, SatoshiLong, Script}
25+
import fr.acinq.bitcoin.scalacompat.{ByteVector32, Satoshi, SatoshiLong, Script}
2626
import fr.acinq.eclair.Features.Wumbo
2727
import fr.acinq.eclair.blockchain.OnChainPubkeyCache
2828
import fr.acinq.eclair.channel._
@@ -31,7 +31,7 @@ import fr.acinq.eclair.io.Peer.{OpenChannelResponse, SpawnChannelNonInitiator}
3131
import fr.acinq.eclair.io.PendingChannelsRateLimiter.AddOrRejectChannel
3232
import fr.acinq.eclair.wire.protocol
3333
import fr.acinq.eclair.wire.protocol.{Error, LiquidityAds, NodeAddress}
34-
import fr.acinq.eclair.{AcceptOpenChannel, CltvExpiryDelta, Features, InitFeature, InterceptOpenChannelPlugin, InterceptOpenChannelReceived, InterceptOpenChannelResponse, Logs, MilliSatoshi, NodeParams, RejectOpenChannel, ToMilliSatoshiConversion}
34+
import fr.acinq.eclair.{AcceptOpenChannel, CltvExpiryDelta, Features, InitFeature, InterceptOpenChannelPlugin, InterceptOpenChannelReceived, InterceptOpenChannelResponse, Logs, MilliSatoshi, NodeParams, RejectOpenChannel, UInt64}
3535
import scodec.bits.ByteVector
3636

3737
import scala.concurrent.duration.{DurationInt, FiniteDuration}
@@ -72,7 +72,7 @@ object OpenChannelInterceptor {
7272

7373
/** DefaultParams are a subset of ChannelData.LocalParams that can be modified by an InterceptOpenChannelPlugin */
7474
case class DefaultParams(dustLimit: Satoshi,
75-
maxHtlcValueInFlightMsat: MilliSatoshi,
75+
maxHtlcValueInFlightMsat: UInt64,
7676
htlcMinimum: MilliSatoshi,
7777
toSelfDelay: CltvExpiryDelta,
7878
maxAcceptedHtlcs: Int)
@@ -84,24 +84,12 @@ object OpenChannelInterceptor {
8484
}
8585
}
8686

87-
private def computeMaxHtlcValueInFlight(nodeParams: NodeParams, fundingAmount: Satoshi, unlimitedMaxHtlcValueInFlight: Boolean): MilliSatoshi = {
88-
if (unlimitedMaxHtlcValueInFlight) {
89-
// We don't want to impose limits on the amount in flight, typically to allow fully emptying the channel.
90-
21e6.btc.toMilliSatoshi
91-
} else {
92-
// NB: when we're the initiator, we don't know yet if the remote peer will contribute to the funding amount, so
93-
// the percentage-based value may be underestimated. That's ok, this is a security parameter so it makes sense to
94-
// base it on the amount that we're contributing instead of the total funding amount.
95-
nodeParams.channelConf.maxHtlcValueInFlightMsat.min(fundingAmount * nodeParams.channelConf.maxHtlcValueInFlightPercent / 100)
96-
}
97-
}
98-
9987
def makeChannelParams(nodeParams: NodeParams, initFeatures: Features[InitFeature], upfrontShutdownScript_opt: Option[ByteVector], walletStaticPaymentBasepoint_opt: Option[PublicKey], isChannelOpener: Boolean, paysCommitTxFees: Boolean, dualFunded: Boolean, fundingAmount: Satoshi, unlimitedMaxHtlcValueInFlight: Boolean): LocalParams = {
10088
LocalParams(
10189
nodeParams.nodeId,
10290
nodeParams.channelKeyManager.newFundingKeyPath(isChannelOpener),
10391
dustLimit = nodeParams.channelConf.dustLimit,
104-
maxHtlcValueInFlightMsat = computeMaxHtlcValueInFlight(nodeParams, fundingAmount, unlimitedMaxHtlcValueInFlight),
92+
maxHtlcValueInFlightMsat = nodeParams.channelConf.maxHtlcValueInFlight(fundingAmount, unlimitedMaxHtlcValueInFlight),
10593
initialRequestedChannelReserve_opt = if (dualFunded) None else Some((fundingAmount * nodeParams.channelConf.reserveToFundingRatio).max(nodeParams.channelConf.dustLimit)), // BOLT #2: make sure that our reserve is above our dust limit
10694
htlcMinimum = nodeParams.channelConf.htlcMinimum,
10795
toSelfDelay = nodeParams.channelConf.toRemoteDelay, // we choose their delay
@@ -216,7 +204,7 @@ private class OpenChannelInterceptor(peer: ActorRef[Any],
216204
case Some(requestFunding) if Features.canUseFeature(request.localFeatures, request.remoteFeatures, Features.OnTheFlyFunding) && localParams.paysCommitTxFees =>
217205
val addFunding = LiquidityAds.AddFunding(requestFunding.requestedAmount, nodeParams.liquidityAdsConfig.rates_opt)
218206
// Now that we know how much we'll contribute to the funding transaction, we update the maxHtlcValueInFlight.
219-
val maxHtlcValueInFlight = localParams.maxHtlcValueInFlightMsat.max(computeMaxHtlcValueInFlight(nodeParams, request.fundingAmount + addFunding.fundingAmount, unlimitedMaxHtlcValueInFlight = false))
207+
val maxHtlcValueInFlight = Seq(localParams.maxHtlcValueInFlightMsat, nodeParams.channelConf.maxHtlcValueInFlight(request.fundingAmount + addFunding.fundingAmount, unlimited = false)).max
220208
val localParams1 = localParams.copy(maxHtlcValueInFlightMsat = maxHtlcValueInFlight)
221209
val accept = SpawnChannelNonInitiator(request.open, ChannelConfig.standard, channelType, Some(addFunding), localParams1, request.peerConnection.toClassic)
222210
checkNoExistingChannel(request, accept)

eclair-core/src/main/scala/fr/acinq/eclair/router/Graph.scala

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package fr.acinq.eclair.router
1818

1919
import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
20-
import fr.acinq.bitcoin.scalacompat.{Btc, BtcDouble, MilliBtc, Satoshi}
20+
import fr.acinq.bitcoin.scalacompat.{Btc, MilliBtc, Satoshi}
2121
import fr.acinq.eclair._
2222
import fr.acinq.eclair.payment.Invoice
2323
import fr.acinq.eclair.payment.relay.Relayer.RelayFees
@@ -381,7 +381,7 @@ object Graph {
381381
val neighborEdges = {
382382
val extraNeighbors = extraEdges.filter(_.desc.b == current.key)
383383
// the resulting set must have only one element per shortChannelId; we prioritize extra edges
384-
g.getIncomingEdgesOf(current.key).collect{case e: GraphEdge if !extraNeighbors.exists(_.desc.shortChannelId == e.desc.shortChannelId) => e} ++ extraNeighbors
384+
g.getIncomingEdgesOf(current.key).collect { case e: GraphEdge if !extraNeighbors.exists(_.desc.shortChannelId == e.desc.shortChannelId) => e } ++ extraNeighbors
385385
}
386386
neighborEdges.foreach { edge =>
387387
val neighbor = edge.desc.a
@@ -512,15 +512,15 @@ object Graph {
512512
object RoutingHeuristics {
513513

514514
// Number of blocks in one year
515-
val BLOCK_TIME_ONE_YEAR = 365 * 24 * 6
515+
val BLOCK_TIME_ONE_YEAR: Int = 365 * 24 * 6
516516

517517
// Low/High bound for channel capacity
518-
val CAPACITY_CHANNEL_LOW = MilliBtc(1).toMilliSatoshi
519-
val CAPACITY_CHANNEL_HIGH = Btc(1).toMilliSatoshi
518+
val CAPACITY_CHANNEL_LOW: MilliSatoshi = MilliBtc(1).toMilliSatoshi
519+
val CAPACITY_CHANNEL_HIGH: MilliSatoshi = Btc(1).toMilliSatoshi
520520

521521
// Low/High bound for CLTV channel value
522-
val CLTV_LOW = 9
523-
val CLTV_HIGH = 2016
522+
val CLTV_LOW: Int = 9
523+
val CLTV_HIGH: Int = 2016
524524

525525
/**
526526
* Normalize the given value between (0, 1). If the @param value is outside the min/max window we flatten it to something very close to the
@@ -571,12 +571,11 @@ object Graph {
571571
)
572572

573573
def apply(e: Invoice.ExtraEdge): GraphEdge = {
574-
val maxBtc = 21e6.btc
575574
GraphEdge(
576575
desc = ChannelDesc(e.shortChannelId, e.sourceNodeId, e.targetNodeId),
577576
params = HopRelayParams.FromHint(e),
578577
// Routing hints don't include the channel's capacity, so we assume it's big enough.
579-
capacity = maxBtc.toSatoshi,
578+
capacity = MilliSatoshi.MaxMoney.truncateToSatoshi,
580579
balance_opt = None,
581580
)
582581
}
@@ -648,9 +647,9 @@ object Graph {
648647
* Update the shortChannelId and capacity of edges corresponding to the given channel-desc,
649648
* both edges (corresponding to both directions) are updated.
650649
*
651-
* @param desc the channel description for the channel to update
650+
* @param desc the channel description for the channel to update
652651
* @param newShortChannelId the new shortChannelId for this channel
653-
* @param newCapacity the new capacity of the channel
652+
* @param newCapacity the new capacity of the channel
654653
* @return a new graph with updated vertexes
655654
*/
656655
def updateChannel(desc: ChannelDesc, newShortChannelId: RealShortChannelId, newCapacity: Satoshi): DirectedGraph = {
@@ -698,8 +697,6 @@ object Graph {
698697
DirectedGraph(removeChannels(channels).vertices - key)
699698
}
700699

701-
def removeVertices(nodeIds: Iterable[PublicKey]): DirectedGraph = nodeIds.foldLeft(this)((acc, nodeId) => acc.removeVertex(nodeId))
702-
703700
/**
704701
* Adds a new vertex to the graph, starting with no edges.
705702
* Or update the node features if the vertex is already present.

eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version0/ChannelCodecs0.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ private[channel] object ChannelCodecs0 {
6161
("nodeId" | publicKey) ::
6262
("channelPath" | keyPathCodec) ::
6363
("dustLimit" | satoshi) ::
64-
("maxHtlcValueInFlightMsat" | millisatoshi) ::
64+
("maxHtlcValueInFlightMsat" | uint64) ::
6565
("channelReserve" | conditional(included = true, satoshi)) ::
6666
("htlcMinimum" | millisatoshi) ::
6767
("toSelfDelay" | cltvExpiryDelta) ::

0 commit comments

Comments
 (0)