Skip to content

Commit 149b8c3

Browse files
authored
On-the-fly channel funding based on splicing and liquidity ads (#649)
* Remove `please_open_channel` It is usually the wallet that decides that it needs a channel, but we want the LSP to pay the commit fees to allow the wallet user to empty its wallet over lightning. We previously used a `please_open_channel` message that was sent by the wallet to the LSP, but it doesn't work well with liquidity ads. We remove that message and instead send `open_channel` from the wallet but with a custom channel flag that tells the LSP that they should be paying the commit fees. This only works if the LSP adds funds on their side of the channel, so we couple that with liquidity ads to request funds from the LSP. We also add a `recommended_feerates` message from the LSP which lets the wallet know the on-chain feerates that the LSP will accept for on-chain funding operations, since those feerates are set in the `open_channel` message that is now sent by the wallet. * Add liquidity ads to the channel opening flow We previously only used liquidity ads with splicing: we now support it during the initial channel opening flow as well. This lets us add more unit tests, including tests for the case where the node receiving the `open_channel` message is responsible for paying the commitment fees. We also update liquidity ads to use the latest version of the spec from lightning/bolts#1153. This introduces more ways of paying the liquidity fees, to support on-the-fly funding without existing channel balance (not implemented in this commit). Note that we need some backwards-compatibility with the previous liquidity ads types in our state serialization code: when we're in the middle of signing a splice transaction, we may have a legacy liquidity lease in our splice status. We ignore it when finalizing the splice: the only consequence is that we won't store an entry in our DB for that lease, but the channel will otherwise work correctly. * Replace `pay_to_open` with `will_add_htlc` We replace the previous pay-to-open protocol with a new protocol that only relies on liquidity ads for paying fees. We simply transmit HTLCs that cannot be relayed on existing channels with a new message called `will_add_htlc` that contains all the HTLC data. The recipient can verify that the HTLC that would match this promise is valid, and if it wishes to accept that payment, it can trigger a channel open or a splice to purchase the required inbound liquidity. Once that transaction completes, the sender will relay HTLCs matching the proposed `will_add_htlc`, which completes the payment. If the fees for the inbound liquidity purchase couldn't be paid from the previous channel balance, they can be taken from the HTLCs relayed after the funding transaction. When that happens, one side needs to trust that the other will comply. Each side can independently configure the options they're comfortable with, depending on whether they trust their peer or not. * Add `channelCreationFee` to liquidity ads Creating a new channel has an additional cost compared to adding liquidity to an existing channel: the channel will be closed in the future, which will require paying on-chain fees. Node operators can include a `channel-creation-fee-satoshis` in their liquidity ads to cover some of that future cost. * Clarify received amount before or after fees We clarify some of our event types that previously had an `amount` field to detail whether this amount includes fees or not. This impacts: - SwapInEvents.Accepted - StoreIncomingPayment.ViaNewChannel - StoreIncomingPayment.ViaSpliceIn - Origin.OnChainWallet - Origin.OffChainPayment There was an inconsistency in the `ViaSpliceIn` event, where in some cases we used the received amount, and in others the amount with fees. * Remove `minInboundLiquidityTarget` We previously forced wallets to purchase additional inbound liquidity every time an on-chain transaction was created. We now allow wallets to disable automatic liquidity purchases: the LSP will need to add enough funds on their side to cover the commitment fees, which the wallet won't be paying for. But we still make a dummy purchase of 1 sat to ensure that the liquidity ads flow is used and the wallet refunds the mining fees paid by the LSP. * Read remote funding rates from their `init` message Instead of using a hard-coded value from `WalletParams`, we read the liquidity funding rates from our peer's `init` message.
1 parent 0d85f88 commit 149b8c3

File tree

117 files changed

+3505
-2196
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+3505
-2196
lines changed

src/commonMain/kotlin/fr/acinq/lightning/Features.kt

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ sealed class Feature {
126126
override val scopes: Set<FeatureScope> get() = setOf(FeatureScope.Init, FeatureScope.Node)
127127
}
128128

129+
@Serializable
130+
object Quiescence : Feature() {
131+
override val rfcName get() = "option_quiescence"
132+
override val mandatory get() = 34
133+
override val scopes: Set<FeatureScope> get() = setOf(FeatureScope.Init, FeatureScope.Node)
134+
}
135+
129136
@Serializable
130137
object ChannelType : Feature() {
131138
override val rfcName get() = "option_channel_type"
@@ -185,15 +192,15 @@ sealed class Feature {
185192
override val scopes: Set<FeatureScope> get() = setOf(FeatureScope.Init, FeatureScope.Node)
186193
}
187194

188-
/** This feature bit should be activated when a node accepts on-the-fly channel creation. */
195+
/** DEPRECATED: this feature bit was used for the legacy pay-to-open protocol. */
189196
@Serializable
190197
object PayToOpenClient : Feature() {
191198
override val rfcName get() = "pay_to_open_client"
192199
override val mandatory get() = 136
193200
override val scopes: Set<FeatureScope> get() = setOf(FeatureScope.Init)
194201
}
195202

196-
/** This feature bit should be activated when a node supports opening channels on-the-fly when liquidity is missing to receive a payment. */
203+
/** DEPRECATED: this feature bit was used for the legacy pay-to-open protocol. */
197204
@Serializable
198205
object PayToOpenProvider : Feature() {
199206
override val rfcName get() = "pay_to_open_provider"
@@ -250,9 +257,9 @@ sealed class Feature {
250257
}
251258

252259
@Serializable
253-
object Quiescence : Feature() {
254-
override val rfcName get() = "option_quiescence"
255-
override val mandatory get() = 34
260+
object OnTheFlyFunding : Feature() {
261+
override val rfcName get() = "on_the_fly_funding"
262+
override val mandatory get() = 560
256263
override val scopes: Set<FeatureScope> get() = setOf(FeatureScope.Init, FeatureScope.Node)
257264
}
258265

@@ -322,6 +329,7 @@ data class Features(val activated: Map<Feature, FeatureSupport>, val unknown: Se
322329
Feature.RouteBlinding,
323330
Feature.ShutdownAnySegwit,
324331
Feature.DualFunding,
332+
Feature.Quiescence,
325333
Feature.ChannelType,
326334
Feature.PaymentMetadata,
327335
Feature.TrampolinePayment,
@@ -337,7 +345,7 @@ data class Features(val activated: Map<Feature, FeatureSupport>, val unknown: Se
337345
Feature.ChannelBackupClient,
338346
Feature.ChannelBackupProvider,
339347
Feature.ExperimentalSplice,
340-
Feature.Quiescence
348+
Feature.OnTheFlyFunding
341349
)
342350

343351
operator fun invoke(bytes: ByteVector): Features = invoke(bytes.toByteArray())
@@ -369,7 +377,8 @@ data class Features(val activated: Map<Feature, FeatureSupport>, val unknown: Se
369377
Feature.BasicMultiPartPayment to listOf(Feature.PaymentSecret),
370378
Feature.AnchorOutputs to listOf(Feature.StaticRemoteKey),
371379
Feature.TrampolinePayment to listOf(Feature.PaymentSecret),
372-
Feature.ExperimentalTrampolinePayment to listOf(Feature.PaymentSecret)
380+
Feature.ExperimentalTrampolinePayment to listOf(Feature.PaymentSecret),
381+
Feature.OnTheFlyFunding to listOf(Feature.ExperimentalSplice)
373382
)
374383

375384
class FeatureException(message: String) : IllegalArgumentException(message)

src/commonMain/kotlin/fr/acinq/lightning/NodeEvents.kt

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package fr.acinq.lightning
22

33
import fr.acinq.bitcoin.ByteVector32
44
import fr.acinq.bitcoin.PublicKey
5+
import fr.acinq.bitcoin.OutPoint
56
import fr.acinq.bitcoin.Satoshi
7+
import fr.acinq.lightning.blockchain.electrum.WalletState
8+
import fr.acinq.lightning.channel.ChannelManagementFees
69
import fr.acinq.lightning.channel.InteractiveTxParams
710
import fr.acinq.lightning.channel.SharedFundingInput
811
import fr.acinq.lightning.channel.states.ChannelStateWithCommitments
@@ -11,16 +14,18 @@ import fr.acinq.lightning.channel.states.WaitForFundingCreated
1114
import fr.acinq.lightning.db.IncomingPayment
1215
import fr.acinq.lightning.utils.sum
1316
import fr.acinq.lightning.wire.Init
14-
import fr.acinq.lightning.wire.PleaseOpenChannel
15-
import kotlinx.coroutines.CompletableDeferred
1617

1718
sealed interface NodeEvents
1819

1920
data class PeerConnected(val remoteNodeId: PublicKey, val theirInit: Init) : NodeEvents
2021

2122
sealed interface SwapInEvents : NodeEvents {
22-
data class Requested(val req: PleaseOpenChannel) : SwapInEvents
23-
data class Accepted(val requestId: ByteVector32, val serviceFee: MilliSatoshi, val miningFee: Satoshi) : SwapInEvents
23+
data class Requested(val walletInputs: List<WalletState.Utxo>) : SwapInEvents {
24+
val totalAmount: Satoshi = walletInputs.map { it.amount }.sum()
25+
}
26+
data class Accepted(val inputs: Set<OutPoint>, val amountBeforeFees: Satoshi, val fees: ChannelManagementFees) : SwapInEvents {
27+
val receivedAmount: Satoshi = amountBeforeFees - fees.total
28+
}
2429
}
2530

2631
sealed interface ChannelEvents : NodeEvents {
@@ -30,6 +35,7 @@ sealed interface ChannelEvents : NodeEvents {
3035
}
3136

3237
sealed interface LiquidityEvents : NodeEvents {
38+
/** Amount of liquidity purchased, before fees are paid. */
3339
val amount: MilliSatoshi
3440
val fee: MilliSatoshi
3541
val source: Source
@@ -42,11 +48,13 @@ sealed interface LiquidityEvents : NodeEvents {
4248
data class OverAbsoluteFee(val maxAbsoluteFee: Satoshi) : TooExpensive()
4349
data class OverRelativeFee(val maxRelativeFeeBasisPoints: Int) : TooExpensive()
4450
}
45-
data object ChannelInitializing : Reason()
51+
data object ChannelFundingInProgress : Reason()
52+
data object NoMatchingFundingRate : Reason()
53+
data class MissingOffChainAmountTooLow(val missingOffChainAmount: MilliSatoshi) : Reason()
54+
data class TooManyParts(val parts: Int) : Reason()
4655
}
4756
}
48-
49-
data class ApprovalRequested(override val amount: MilliSatoshi, override val fee: MilliSatoshi, override val source: Source, val replyTo: CompletableDeferred<Boolean>) : LiquidityEvents
57+
data class Accepted(override val amount: MilliSatoshi, override val fee: MilliSatoshi, override val source: Source) : LiquidityEvents
5058
}
5159

5260
/** This is useful on iOS to ask the OS for time to finish some sensitive tasks. */
@@ -59,15 +67,14 @@ sealed interface SensitiveTaskEvents : NodeEvents {
5967
}
6068
data class TaskStarted(val id: TaskIdentifier) : SensitiveTaskEvents
6169
data class TaskEnded(val id: TaskIdentifier) : SensitiveTaskEvents
62-
6370
}
6471

6572
/** This will be emitted in a corner case where the user restores a wallet on an older version of the app, which is unable to read the channel data. */
6673
data object UpgradeRequired : NodeEvents
6774

6875
sealed interface PaymentEvents : NodeEvents {
6976
data class PaymentReceived(val paymentHash: ByteVector32, val receivedWith: List<IncomingPayment.ReceivedWith>) : PaymentEvents {
70-
val amount: MilliSatoshi = receivedWith.map { it.amount }.sum()
77+
val amount: MilliSatoshi = receivedWith.map { it.amountReceived }.sum()
7178
val fees: MilliSatoshi = receivedWith.map { it.fees }.sum()
7279
}
7380
}

src/commonMain/kotlin/fr/acinq/lightning/NodeParams.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import fr.acinq.lightning.payment.LiquidityPolicy
1212
import fr.acinq.lightning.utils.msat
1313
import fr.acinq.lightning.utils.sat
1414
import fr.acinq.lightning.utils.toMilliSatoshi
15+
import fr.acinq.lightning.wire.LiquidityAds
1516
import fr.acinq.lightning.wire.OfferTypes
1617
import io.ktor.utils.io.charsets.*
1718
import io.ktor.utils.io.core.*
@@ -172,6 +173,8 @@ data class NodeParams(
172173
require(!features.hasFeature(Feature.ZeroConfChannels)) { "${Feature.ZeroConfChannels.rfcName} has been deprecated: use the zeroConfPeers whitelist instead" }
173174
require(!features.hasFeature(Feature.TrustedSwapInClient)) { "${Feature.TrustedSwapInClient.rfcName} has been deprecated" }
174175
require(!features.hasFeature(Feature.TrustedSwapInProvider)) { "${Feature.TrustedSwapInProvider.rfcName} has been deprecated" }
176+
require(!features.hasFeature(Feature.PayToOpenClient)) { "${Feature.PayToOpenClient.rfcName} has been deprecated" }
177+
require(!features.hasFeature(Feature.PayToOpenProvider)) { "${Feature.PayToOpenProvider.rfcName} has been deprecated" }
175178
Features.validateFeatureGraph(features)
176179
}
177180

@@ -193,15 +196,15 @@ data class NodeParams(
193196
Feature.RouteBlinding to FeatureSupport.Optional,
194197
Feature.DualFunding to FeatureSupport.Mandatory,
195198
Feature.ShutdownAnySegwit to FeatureSupport.Mandatory,
199+
Feature.Quiescence to FeatureSupport.Mandatory,
196200
Feature.ChannelType to FeatureSupport.Mandatory,
197201
Feature.PaymentMetadata to FeatureSupport.Optional,
198202
Feature.ExperimentalTrampolinePayment to FeatureSupport.Optional,
199203
Feature.ZeroReserveChannels to FeatureSupport.Optional,
200204
Feature.WakeUpNotificationClient to FeatureSupport.Optional,
201-
Feature.PayToOpenClient to FeatureSupport.Optional,
202205
Feature.ChannelBackupClient to FeatureSupport.Optional,
203206
Feature.ExperimentalSplice to FeatureSupport.Optional,
204-
Feature.Quiescence to FeatureSupport.Mandatory
207+
Feature.OnTheFlyFunding to FeatureSupport.Optional,
205208
),
206209
dustLimit = 546.sat,
207210
maxRemoteDustLimit = 600.sat,
@@ -229,7 +232,7 @@ data class NodeParams(
229232
maxPaymentAttempts = 5,
230233
zeroConfPeers = emptySet(),
231234
paymentRecipientExpiryParams = RecipientCltvExpiryParams(CltvExpiryDelta(75), CltvExpiryDelta(200)),
232-
liquidityPolicy = MutableStateFlow<LiquidityPolicy>(LiquidityPolicy.Auto(maxAbsoluteFee = 2_000.sat, maxRelativeFeeBasisPoints = 3_000 /* 3000 = 30 % */, skipAbsoluteFeeCheck = false)),
235+
liquidityPolicy = MutableStateFlow<LiquidityPolicy>(LiquidityPolicy.Auto(inboundLiquidityTarget = null, maxAbsoluteFee = 2_000.sat, maxRelativeFeeBasisPoints = 3_000 /* 3000 = 30 % */, skipAbsoluteFeeCheck = false)),
233236
minFinalCltvExpiryDelta = Bolt11Invoice.DEFAULT_MIN_FINAL_EXPIRY_DELTA,
234237
maxFinalCltvExpiryDelta = CltvExpiryDelta(360),
235238
bolt12invoiceExpiry = 60.seconds,

src/commonMain/kotlin/fr/acinq/lightning/blockchain/electrum/SwapInManager.kt

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,18 @@ package fr.acinq.lightning.blockchain.electrum
22

33
import fr.acinq.bitcoin.OutPoint
44
import fr.acinq.bitcoin.Transaction
5-
import fr.acinq.bitcoin.TxId
6-
import fr.acinq.lightning.Lightning
75
import fr.acinq.lightning.SwapInParams
86
import fr.acinq.lightning.channel.FundingContributions.Companion.stripInputWitnesses
97
import fr.acinq.lightning.channel.LocalFundingStatus
108
import fr.acinq.lightning.channel.RbfStatus
11-
import fr.acinq.lightning.channel.SignedSharedTransaction
129
import fr.acinq.lightning.channel.SpliceStatus
1310
import fr.acinq.lightning.channel.states.*
14-
import fr.acinq.lightning.io.RequestChannelOpen
11+
import fr.acinq.lightning.io.AddWalletInputsToChannel
1512
import fr.acinq.lightning.logging.MDCLogger
1613
import fr.acinq.lightning.utils.sat
1714

1815
internal sealed class SwapInCommand {
19-
data class TrySwapIn(val currentBlockHeight: Int, val wallet: WalletState, val swapInParams: SwapInParams, val trustedTxs: Set<TxId>) : SwapInCommand()
16+
data class TrySwapIn(val currentBlockHeight: Int, val wallet: WalletState, val swapInParams: SwapInParams) : SwapInCommand()
2017
data class UnlockWalletInputs(val inputs: Set<OutPoint>) : SwapInCommand()
2118
}
2219

@@ -33,20 +30,15 @@ internal sealed class SwapInCommand {
3330
class SwapInManager(private var reservedUtxos: Set<OutPoint>, private val logger: MDCLogger) {
3431
constructor(bootChannels: List<PersistedChannelState>, logger: MDCLogger) : this(reservedWalletInputs(bootChannels), logger)
3532

36-
internal fun process(cmd: SwapInCommand): RequestChannelOpen? = when (cmd) {
33+
internal fun process(cmd: SwapInCommand): AddWalletInputsToChannel? = when (cmd) {
3734
is SwapInCommand.TrySwapIn -> {
3835
val availableWallet = cmd.wallet.withoutReservedUtxos(reservedUtxos).withConfirmations(cmd.currentBlockHeight, cmd.swapInParams)
3936
logger.info { "swap-in wallet balance: deeplyConfirmed=${availableWallet.deeplyConfirmed.balance}, weaklyConfirmed=${availableWallet.weaklyConfirmed.balance}, unconfirmed=${availableWallet.unconfirmed.balance}" }
40-
val utxos = buildSet {
41-
// some utxos may be used for swap-in even if they are not confirmed, for example when migrating from the legacy phoenix android app
42-
addAll(availableWallet.unconfirmed.filter { cmd.trustedTxs.contains(it.outPoint.txid) })
43-
addAll(availableWallet.weaklyConfirmed.filter { cmd.trustedTxs.contains(it.outPoint.txid) })
44-
addAll(availableWallet.deeplyConfirmed.filter { Transaction.write(it.previousTx.stripInputWitnesses()).size < 65_000 })
45-
}.toList()
37+
val utxos = availableWallet.deeplyConfirmed.filter { Transaction.write(it.previousTx.stripInputWitnesses()).size < 65_000 }
4638
if (utxos.balance > 0.sat) {
4739
logger.info { "swap-in wallet: requesting channel using ${utxos.size} utxos with balance=${utxos.balance}" }
4840
reservedUtxos = reservedUtxos.union(utxos.map { it.outPoint })
49-
RequestChannelOpen(Lightning.randomBytes32(), utxos)
41+
AddWalletInputsToChannel(utxos)
5042
} else {
5143
null
5244
}

src/commonMain/kotlin/fr/acinq/lightning/channel/ChannelAction.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package fr.acinq.lightning.channel
22

33
import fr.acinq.bitcoin.*
4-
import fr.acinq.lightning.ChannelEvents
54
import fr.acinq.lightning.CltvExpiry
65
import fr.acinq.lightning.MilliSatoshi
6+
import fr.acinq.lightning.NodeEvents
77
import fr.acinq.lightning.blockchain.Watch
88
import fr.acinq.lightning.channel.states.PersistedChannelState
99
import fr.acinq.lightning.db.ChannelClosingType
1010
import fr.acinq.lightning.transactions.Transactions
1111
import fr.acinq.lightning.utils.UUID
12+
import fr.acinq.lightning.utils.toMilliSatoshi
1213
import fr.acinq.lightning.wire.*
1314

1415
/** Channel Actions (outputs produced by the state machine). */
@@ -78,16 +79,16 @@ sealed class ChannelAction {
7879
abstract val origin: Origin?
7980
abstract val txId: TxId
8081
abstract val localInputs: Set<OutPoint>
81-
data class ViaNewChannel(val amount: MilliSatoshi, val serviceFee: MilliSatoshi, val miningFee: Satoshi, override val localInputs: Set<OutPoint>, override val txId: TxId, override val origin: Origin?) : StoreIncomingPayment()
82-
data class ViaSpliceIn(val amount: MilliSatoshi, val serviceFee: MilliSatoshi, val miningFee: Satoshi, override val localInputs: Set<OutPoint>, override val txId: TxId, override val origin: Origin.PayToOpenOrigin?) : StoreIncomingPayment()
82+
data class ViaNewChannel(val amountReceived: MilliSatoshi, val serviceFee: MilliSatoshi, val miningFee: Satoshi, override val localInputs: Set<OutPoint>, override val txId: TxId, override val origin: Origin?) : StoreIncomingPayment()
83+
data class ViaSpliceIn(val amountReceived: MilliSatoshi, val serviceFee: MilliSatoshi, val miningFee: Satoshi, override val localInputs: Set<OutPoint>, override val txId: TxId, override val origin: Origin?) : StoreIncomingPayment()
8384
}
8485
/** Payment sent through on-chain operations (channel close or splice-out) */
8586
sealed class StoreOutgoingPayment : Storage() {
8687
abstract val miningFees: Satoshi
8788
abstract val txId: TxId
8889
data class ViaSpliceOut(val amount: Satoshi, override val miningFees: Satoshi, val address: String, override val txId: TxId) : StoreOutgoingPayment()
8990
data class ViaSpliceCpfp(override val miningFees: Satoshi, override val txId: TxId) : StoreOutgoingPayment()
90-
data class ViaInboundLiquidityRequest(override val txId: TxId, override val miningFees: Satoshi, val lease: LiquidityAds.Lease) : StoreOutgoingPayment()
91+
data class ViaInboundLiquidityRequest(override val txId: TxId, override val miningFees: Satoshi, val purchase: LiquidityAds.Purchase) : StoreOutgoingPayment()
9192
data class ViaClose(val amount: Satoshi, override val miningFees: Satoshi, val address: String, override val txId: TxId, val isSentToDefaultAddress: Boolean, val closingType: ChannelClosingType) : StoreOutgoingPayment()
9293
}
9394
data class SetLocked(val txId: TxId) : Storage()
@@ -128,8 +129,8 @@ sealed class ChannelAction {
128129
}
129130
}
130131

131-
data class EmitEvent(val event: ChannelEvents) : ChannelAction()
132+
data class EmitEvent(val event: NodeEvents) : ChannelAction()
132133

133-
object Disconnect : ChannelAction()
134+
data object Disconnect : ChannelAction()
134135
// @formatter:on
135136
}

src/commonMain/kotlin/fr/acinq/lightning/channel/ChannelCommand.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ sealed class ChannelCommand {
3232
val fundingTxFeerate: FeeratePerKw,
3333
val localParams: LocalParams,
3434
val remoteInit: InitMessage,
35-
val channelFlags: Byte,
35+
val channelFlags: ChannelFlags,
3636
val channelConfig: ChannelConfig,
3737
val channelType: ChannelType.SupportedChannelType,
38-
val channelOrigin: Origin? = null
38+
val requestRemoteFunding: LiquidityAds.RequestFunding?,
39+
val channelOrigin: Origin?,
3940
) : Init() {
4041
fun temporaryChannelId(keyManager: KeyManager): ByteVector32 = keyManager.channelKeys(localParams.fundingKeyPath).temporaryChannelId
4142
}
@@ -47,7 +48,8 @@ sealed class ChannelCommand {
4748
val walletInputs: List<WalletState.Utxo>,
4849
val localParams: LocalParams,
4950
val channelConfig: ChannelConfig,
50-
val remoteInit: InitMessage
51+
val remoteInit: InitMessage,
52+
val fundingRates: LiquidityAds.WillFundRates?
5153
) : Init()
5254

5355
data class Restore(val state: PersistedChannelState) : Init()
@@ -85,7 +87,7 @@ sealed class ChannelCommand {
8587
data class UpdateFee(val feerate: FeeratePerKw, val commit: Boolean = false) : Commitment(), ForbiddenDuringSplice, ForbiddenDuringQuiescence
8688
data object CheckHtlcTimeout : Commitment()
8789
sealed class Splice : Commitment() {
88-
data class Request(val replyTo: CompletableDeferred<Response>, val spliceIn: SpliceIn?, val spliceOut: SpliceOut?, val requestRemoteFunding: LiquidityAds.RequestRemoteFunding?, val feerate: FeeratePerKw, val origins: List<Origin.PayToOpenOrigin> = emptyList()) : Splice() {
90+
data class Request(val replyTo: CompletableDeferred<Response>, val spliceIn: SpliceIn?, val spliceOut: SpliceOut?, val requestRemoteFunding: LiquidityAds.RequestFunding?, val feerate: FeeratePerKw, val origins: List<Origin>) : Splice() {
8991
val pushAmount: MilliSatoshi = spliceIn?.pushAmount ?: 0.msat
9092
val spliceOutputs: List<TxOut> = spliceOut?.let { listOf(TxOut(it.amount, it.scriptPubKey)) } ?: emptyList()
9193

@@ -104,7 +106,7 @@ sealed class ChannelCommand {
104106
val fundingTxId: TxId,
105107
val capacity: Satoshi,
106108
val balance: MilliSatoshi,
107-
val liquidityLease: LiquidityAds.Lease?,
109+
val liquidityPurchase: LiquidityAds.Purchase?,
108110
) : Response()
109111

110112
sealed class Failure : Response() {

0 commit comments

Comments
 (0)