Skip to content

Commit

Permalink
Remove support for push_amount (#697)
Browse files Browse the repository at this point in the history
With the updated on-the-fly funding protocol, we're using liquidity ads
instead of an unofficial `push_amount` TLV. We can thus remove usage of
`push_amount`s everywhere, which simplifies the codebase.
  • Loading branch information
t-bast authored Oct 22, 2024
1 parent 192f3bf commit a7e4dad
Show file tree
Hide file tree
Showing 34 changed files with 166 additions and 447 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import fr.acinq.lightning.channel.states.ClosingFeerates
import fr.acinq.lightning.channel.states.PersistedChannelState
import fr.acinq.lightning.crypto.KeyManager
import fr.acinq.lightning.utils.UUID
import fr.acinq.lightning.utils.msat
import fr.acinq.lightning.wire.FailureMessage
import fr.acinq.lightning.wire.LightningMessage
import fr.acinq.lightning.wire.LiquidityAds
Expand All @@ -27,7 +26,6 @@ sealed class ChannelCommand {
data class Initiator(
val replyTo: CompletableDeferred<ChannelFundingResponse>,
val fundingAmount: Satoshi,
val pushAmount: MilliSatoshi,
val walletInputs: List<WalletState.Utxo>,
val commitTxFeerate: FeeratePerKw,
val fundingTxFeerate: FeeratePerKw,
Expand All @@ -46,7 +44,6 @@ sealed class ChannelCommand {
val replyTo: CompletableDeferred<ChannelFundingResponse>,
val temporaryChannelId: ByteVector32,
val fundingAmount: Satoshi,
val pushAmount: MilliSatoshi,
val walletInputs: List<WalletState.Utxo>,
val localParams: LocalParams,
val channelConfig: ChannelConfig,
Expand Down Expand Up @@ -98,11 +95,10 @@ sealed class ChannelCommand {
val feerate: FeeratePerKw,
val origins: List<Origin>
) : Splice() {
val pushAmount: MilliSatoshi = spliceIn?.pushAmount ?: 0.msat
val spliceOutputs: List<TxOut> = spliceOut?.let { listOf(TxOut(it.amount, it.scriptPubKey)) } ?: emptyList()
val liquidityFees: LiquidityAds.Fees? = requestRemoteFunding?.fees(feerate, isChannelCreation = false)

data class SpliceIn(val walletInputs: List<WalletState.Utxo>, val pushAmount: MilliSatoshi = 0.msat)
data class SpliceIn(val walletInputs: List<WalletState.Utxo>)
data class SpliceOut(val amount: Satoshi, val scriptPubKey: ByteVector)
}
}
Expand Down
9 changes: 0 additions & 9 deletions src/commonMain/kotlin/fr/acinq/lightning/channel/Helpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,6 @@ object Helpers {
return Either.Left(InvalidChainHash(open.temporaryChannelId, local = nodeParams.chainHash, remote = open.chainHash))
}

// BOLT #2: The receiving node MUST fail the channel if: push_msat is greater than funding_satoshis * 1000.
if (open.pushAmount > open.fundingAmount) {
return Either.Left(InvalidPushAmount(open.temporaryChannelId, open.pushAmount, open.fundingAmount.toMilliSatoshi()))
}

// BOLT #2: The receiving node MUST fail the channel if: to_self_delay is unreasonably large.
if (open.toSelfDelay > Channel.MAX_TO_SELF_DELAY || open.toSelfDelay > nodeParams.maxToLocalDelayBlocks) {
return Either.Left(ToSelfDelayTooHigh(open.temporaryChannelId, open.toSelfDelay, nodeParams.maxToLocalDelayBlocks))
Expand Down Expand Up @@ -122,10 +117,6 @@ object Helpers {
return Either.Left(InvalidFundingAmount(accept.temporaryChannelId, accept.fundingAmount))
}

if (accept.pushAmount > accept.fundingAmount) {
return Either.Left(InvalidPushAmount(accept.temporaryChannelId, accept.pushAmount, accept.fundingAmount.toMilliSatoshi()))
}

if (accept.maxAcceptedHtlcs > Channel.MAX_ACCEPTED_HTLCS) {
return Either.Left(InvalidMaxAcceptedHtlcs(accept.temporaryChannelId, accept.maxAcceptedHtlcs, Channel.MAX_ACCEPTED_HTLCS))
}
Expand Down
18 changes: 5 additions & 13 deletions src/commonMain/kotlin/fr/acinq/lightning/channel/InteractiveTx.kt
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,9 @@ data class FundingContributions(val inputs: List<InteractiveTxInput.Outgoing>, v
swapInKeys: KeyManager.SwapInOnChainKeys,
params: InteractiveTxParams,
walletInputs: List<WalletState.Utxo>,
localPushAmount: MilliSatoshi,
remotePushAmount: MilliSatoshi,
liquidityPurchase: LiquidityAds.Purchase?
): Either<FundingContributionFailure, FundingContributions> {
return create(channelKeys, swapInKeys, params, null, walletInputs, listOf(), localPushAmount, remotePushAmount, liquidityPurchase)
return create(channelKeys, swapInKeys, params, null, walletInputs, listOf(), liquidityPurchase)
}

/**
Expand All @@ -290,8 +288,6 @@ data class FundingContributions(val inputs: List<InteractiveTxInput.Outgoing>, v
sharedUtxo: Pair<SharedFundingInput, SharedFundingInputBalances>?,
walletInputs: List<WalletState.Utxo>,
localOutputs: List<TxOut>,
localPushAmount: MilliSatoshi,
remotePushAmount: MilliSatoshi,
liquidityPurchase: LiquidityAds.Purchase?,
changePubKey: PublicKey? = null
): Either<FundingContributionFailure, FundingContributions> {
Expand All @@ -310,9 +306,9 @@ data class FundingContributions(val inputs: List<InteractiveTxInput.Outgoing>, v

val liquidityFees = params.liquidityFees(liquidityPurchase)
val nextLocalBalanceBeforePush = (sharedUtxo?.second?.toLocal ?: 0.msat) + params.localContribution.toMilliSatoshi()
val nextLocalBalanceAfterPush = (sharedUtxo?.second?.toLocal ?: 0.msat) + params.localContribution.toMilliSatoshi() - localPushAmount + remotePushAmount - liquidityFees
val nextLocalBalanceAfterPush = (sharedUtxo?.second?.toLocal ?: 0.msat) + params.localContribution.toMilliSatoshi() - liquidityFees
val nextRemoteBalanceBeforePush = (sharedUtxo?.second?.toRemote ?: 0.msat) + params.remoteContribution.toMilliSatoshi()
val nextRemoteBalanceAfterPush = (sharedUtxo?.second?.toRemote ?: 0.msat) + params.remoteContribution.toMilliSatoshi() + localPushAmount - remotePushAmount + liquidityFees
val nextRemoteBalanceAfterPush = (sharedUtxo?.second?.toRemote ?: 0.msat) + params.remoteContribution.toMilliSatoshi() + liquidityFees
if (nextLocalBalanceAfterPush < 0.msat || nextRemoteBalanceAfterPush < 0.msat) {
return Either.Left(FundingContributionFailure.InvalidFundingBalances(params.fundingAmount, nextLocalBalanceAfterPush, nextRemoteBalanceAfterPush))
}
Expand Down Expand Up @@ -1091,8 +1087,6 @@ data class InteractiveTxSigningSession(
fundingParams: InteractiveTxParams,
fundingTxIndex: Long,
sharedTx: SharedTransaction,
localPushAmount: MilliSatoshi,
remotePushAmount: MilliSatoshi,
liquidityPurchase: LiquidityAds.Purchase?,
localCommitmentIndex: Long,
remoteCommitmentIndex: Long,
Expand All @@ -1109,8 +1103,8 @@ data class InteractiveTxSigningSession(
channelParams.channelId,
channelParams.localParams, channelParams.remoteParams,
fundingAmount = sharedTx.sharedOutput.amount,
toLocal = sharedTx.sharedOutput.localAmount - localPushAmount + remotePushAmount - liquidityFees,
toRemote = sharedTx.sharedOutput.remoteAmount - remotePushAmount + localPushAmount + liquidityFees,
toLocal = sharedTx.sharedOutput.localAmount - liquidityFees,
toRemote = sharedTx.sharedOutput.remoteAmount + liquidityFees,
localHtlcs = localHtlcs,
localCommitmentIndex = localCommitmentIndex,
remoteCommitmentIndex = remoteCommitmentIndex,
Expand Down Expand Up @@ -1203,8 +1197,6 @@ sealed class SpliceStatus {
data class InProgress(
val replyTo: CompletableDeferred<ChannelFundingResponse>?,
val spliceSession: InteractiveTxSession,
val localPushAmount: MilliSatoshi,
val remotePushAmount: MilliSatoshi,
val liquidityPurchase: LiquidityAds.Purchase?,
val origins: List<Origin>
) : QuiescentSpliceStatus()
Expand Down
16 changes: 3 additions & 13 deletions src/commonMain/kotlin/fr/acinq/lightning/channel/states/Normal.kt
Original file line number Diff line number Diff line change
Expand Up @@ -419,10 +419,9 @@ data class Normal(
lockTime = currentBlockHeight.toLong(),
feerate = spliceStatus.command.feerate,
fundingPubkey = channelKeys().fundingPubKey(parentCommitment.fundingTxIndex + 1),
pushAmount = spliceStatus.command.pushAmount,
requestFunding = spliceStatus.command.requestRemoteFunding,
)
logger.info { "initiating splice with local.amount=${spliceInit.fundingContribution} local.push=${spliceInit.pushAmount}" }
logger.info { "initiating splice with local.amount=${spliceInit.fundingContribution}" }
Pair(this@Normal.copy(spliceStatus = SpliceStatus.Requested(spliceStatus.command, spliceInit)), listOf(ChannelAction.Message.Send(spliceInit)))
}
} else {
Expand Down Expand Up @@ -453,12 +452,11 @@ data class Normal(
}
is SpliceStatus.NonInitiatorQuiescent ->
if (commitments.isQuiescent()) {
logger.info { "accepting splice with remote.amount=${cmd.message.fundingContribution} remote.push=${cmd.message.pushAmount}" }
logger.info { "accepting splice with remote.amount=${cmd.message.fundingContribution}" }
val parentCommitment = commitments.active.first()
val spliceAck = SpliceAck(
channelId,
fundingContribution = 0.sat, // only remote contributes to the splice
pushAmount = 0.msat,
fundingPubkey = channelKeys().fundingPubKey(parentCommitment.fundingTxIndex + 1),
willFund = null,
)
Expand Down Expand Up @@ -489,8 +487,6 @@ data class Normal(
spliceStatus = SpliceStatus.InProgress(
replyTo = null,
session,
localPushAmount = 0.msat,
remotePushAmount = cmd.message.pushAmount,
liquidityPurchase = null,
origins = listOf()
)
Expand All @@ -511,7 +507,7 @@ data class Normal(
}
is SpliceAck -> when (spliceStatus) {
is SpliceStatus.Requested -> {
logger.info { "our peer accepted our splice request with remote.amount=${cmd.message.fundingContribution} remote.push=${cmd.message.pushAmount} liquidityFees=${spliceStatus.command.liquidityFees}" }
logger.info { "our peer accepted our splice request with remote.amount=${cmd.message.fundingContribution} liquidityFees=${spliceStatus.command.liquidityFees}" }
when (val liquidityPurchase = LiquidityAds.validateRemoteFunding(
spliceStatus.command.requestRemoteFunding,
remoteNodeId,
Expand Down Expand Up @@ -550,8 +546,6 @@ data class Normal(
sharedUtxo = Pair(sharedInput, SharedFundingInputBalances(toLocal = parentCommitment.localCommit.spec.toLocal, toRemote = parentCommitment.localCommit.spec.toRemote, toHtlcs = parentCommitment.localCommit.spec.htlcs.map { it.add.amountMsat }.sum())),
walletInputs = spliceStatus.command.spliceIn?.walletInputs ?: emptyList(),
localOutputs = spliceStatus.command.spliceOutputs,
localPushAmount = spliceStatus.spliceInit.pushAmount,
remotePushAmount = cmd.message.pushAmount,
liquidityPurchase = liquidityPurchase.value,
changePubKey = null // we don't want a change output: we're spending every funds available
)) {
Expand Down Expand Up @@ -579,8 +573,6 @@ data class Normal(
spliceStatus = SpliceStatus.InProgress(
replyTo = spliceStatus.command.replyTo,
interactiveTxSession,
localPushAmount = spliceStatus.spliceInit.pushAmount,
remotePushAmount = cmd.message.pushAmount,
liquidityPurchase = liquidityPurchase.value,
origins = spliceStatus.command.origins,
)
Expand Down Expand Up @@ -617,8 +609,6 @@ data class Normal(
spliceStatus.spliceSession.fundingParams,
fundingTxIndex = parentCommitment.fundingTxIndex + 1,
interactiveTxAction.sharedTx,
localPushAmount = spliceStatus.localPushAmount,
remotePushAmount = spliceStatus.remotePushAmount,
liquidityPurchase = spliceStatus.liquidityPurchase,
localCommitmentIndex = parentCommitment.localCommit.index,
remoteCommitmentIndex = parentCommitment.remoteCommit.index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ data class WaitForAcceptChannel(
keyManager.swapInOnChainWallet,
fundingParams,
init.walletInputs,
lastSent.pushAmount,
accept.pushAmount,
liquidityPurchase.value
)) {
is Either.Left -> {
Expand All @@ -100,8 +98,6 @@ data class WaitForAcceptChannel(
init.localParams,
remoteParams,
interactiveTxSession,
lastSent.pushAmount,
accept.pushAmount,
lastSent.commitmentFeerate,
accept.firstPerCommitmentPoint,
accept.secondPerCommitmentPoint,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@ package fr.acinq.lightning.channel.states

import fr.acinq.bitcoin.TxId
import fr.acinq.bitcoin.utils.Either
import fr.acinq.lightning.MilliSatoshi
import fr.acinq.lightning.ShortChannelId
import fr.acinq.lightning.blockchain.BITCOIN_FUNDING_DEPTHOK
import fr.acinq.lightning.blockchain.WatchConfirmed
import fr.acinq.lightning.blockchain.WatchEventConfirmed
import fr.acinq.lightning.channel.*
import fr.acinq.lightning.utils.msat
import fr.acinq.lightning.utils.toMilliSatoshi
import fr.acinq.lightning.wire.*

/** We wait for the channel funding transaction to confirm. */
data class WaitForFundingConfirmed(
override val commitments: Commitments,
val localPushAmount: MilliSatoshi,
val remotePushAmount: MilliSatoshi,
val waitingSinceBlock: Long, // how many blocks have we been waiting for the funding tx to confirm
val deferred: ChannelReady?,
// We can have at most one ongoing RBF attempt.
Expand Down Expand Up @@ -85,12 +81,6 @@ data class WaitForFundingConfirmed(
if (cmd.message.feerate < minNextFeerate) {
logger.info { "rejecting rbf attempt: the new feerate must be at least $minNextFeerate (proposed=${cmd.message.feerate})" }
Pair(this@WaitForFundingConfirmed.copy(rbfStatus = RbfStatus.RbfAborted), listOf(ChannelAction.Message.Send(TxAbort(channelId, InvalidRbfFeerate(channelId, cmd.message.feerate, minNextFeerate).message))))
} else if (cmd.message.fundingContribution.toMilliSatoshi() < remotePushAmount) {
logger.info { "rejecting rbf attempt: invalid amount pushed (fundingAmount=${cmd.message.fundingContribution}, pushAmount=$remotePushAmount)" }
Pair(
this@WaitForFundingConfirmed.copy(rbfStatus = RbfStatus.RbfAborted),
listOf(ChannelAction.Message.Send(TxAbort(channelId, InvalidPushAmount(channelId, remotePushAmount, cmd.message.fundingContribution.toMilliSatoshi()).message)))
)
} else {
logger.info { "our peer wants to raise the feerate of the funding transaction (previous=${latestFundingTx.fundingParams.targetFeerate} target=${cmd.message.feerate})" }
val fundingParams = InteractiveTxParams(
Expand Down Expand Up @@ -136,7 +126,7 @@ data class WaitForFundingConfirmed(
latestFundingTx.fundingParams.dustLimit,
rbfStatus.command.targetFeerate
)
when (val contributions = FundingContributions.create(channelKeys(), keyManager.swapInOnChainWallet, fundingParams, rbfStatus.command.walletInputs, 0.msat, 0.msat, null)) {
when (val contributions = FundingContributions.create(channelKeys(), keyManager.swapInOnChainWallet, fundingParams, rbfStatus.command.walletInputs, null)) {
is Either.Left -> {
logger.warning { "error creating funding contributions: ${contributions.value}" }
Pair(this@WaitForFundingConfirmed.copy(rbfStatus = RbfStatus.RbfAborted), listOf(ChannelAction.Message.Send(TxAbort(channelId, ChannelFundingError(channelId).message))))
Expand Down Expand Up @@ -175,8 +165,6 @@ data class WaitForFundingConfirmed(
rbfSession1.fundingParams,
fundingTxIndex = replacedCommitment.fundingTxIndex,
interactiveTxAction.sharedTx,
localPushAmount,
remotePushAmount,
liquidityPurchase = null,
localCommitmentIndex = replacedCommitment.localCommit.index,
remoteCommitmentIndex = replacedCommitment.remoteCommit.index,
Expand Down Expand Up @@ -321,8 +309,6 @@ data class WaitForFundingConfirmed(
val watchConfirmed = WatchConfirmed(channelId, action.commitment.fundingTxId, action.commitment.commitInput.txOut.publicKeyScript, fundingMinDepth.toLong(), BITCOIN_FUNDING_DEPTHOK)
val nextState = WaitForFundingConfirmed(
commitments.add(action.commitment).copy(remoteChannelData = remoteChannelData),
localPushAmount,
remotePushAmount,
waitingSinceBlock,
deferred,
RbfStatus.None
Expand Down
Loading

0 comments on commit a7e4dad

Please sign in to comment.