mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 09:53:54 +01:00
lnwallet+size: select HTLC fees based on channel type
This commit is contained in:
parent
ea2a58e80f
commit
b7885dbbae
@ -202,6 +202,23 @@ const (
|
|||||||
// which will transition an incoming HTLC to the delay-and-claim state.
|
// which will transition an incoming HTLC to the delay-and-claim state.
|
||||||
HtlcSuccessWeight = 703
|
HtlcSuccessWeight = 703
|
||||||
|
|
||||||
|
// HtlcConfirmedScriptOverhead is the extra length of an HTLC script
|
||||||
|
// that requires confirmation before it can be spent. These extra bytes
|
||||||
|
// is a result of the extra CSV check.
|
||||||
|
HtlcConfirmedScriptOverhead = 3
|
||||||
|
|
||||||
|
// HtlcTimeoutWeightConfirmed is the weight of the HTLC timeout
|
||||||
|
// transaction which will transition an outgoing HTLC to the
|
||||||
|
// delay-and-claim state, for the confirmed HTLC outputs. It is 3 bytes
|
||||||
|
// larger because of the additional CSV check in the input script.
|
||||||
|
HtlcTimeoutWeightConfirmed = HtlcTimeoutWeight + HtlcConfirmedScriptOverhead
|
||||||
|
|
||||||
|
// HtlcSuccessWeightCOnfirmed is the weight of the HTLC success
|
||||||
|
// transaction which will transition an incoming HTLC to the
|
||||||
|
// delay-and-claim state, for the confirmed HTLC outputs. It is 3 bytes
|
||||||
|
// larger because of the cdditional CSV check in the input script.
|
||||||
|
HtlcSuccessWeightConfirmed = HtlcSuccessWeight + HtlcConfirmedScriptOverhead
|
||||||
|
|
||||||
// MaxHTLCNumber is the maximum number HTLCs which can be included in a
|
// MaxHTLCNumber is the maximum number HTLCs which can be included in a
|
||||||
// commitment transaction. This limit was chosen such that, in the case
|
// commitment transaction. This limit was chosen such that, in the case
|
||||||
// of a contract breach, the punishment transaction is able to sweep
|
// of a contract breach, the punishment transaction is able to sweep
|
||||||
|
@ -596,7 +596,7 @@ func locateOutputIndex(p *PaymentDescriptor, tx *wire.MsgTx, ourCommit bool,
|
|||||||
// we need to keep track of the indexes of each HTLC in order to properly write
|
// we need to keep track of the indexes of each HTLC in order to properly write
|
||||||
// the current state to disk, and also to locate the PaymentDescriptor
|
// the current state to disk, and also to locate the PaymentDescriptor
|
||||||
// corresponding to HTLC outputs in the commitment transaction.
|
// corresponding to HTLC outputs in the commitment transaction.
|
||||||
func (c *commitment) populateHtlcIndexes() error {
|
func (c *commitment) populateHtlcIndexes(chanType channeldb.ChannelType) error {
|
||||||
// First, we'll set up some state to allow us to locate the output
|
// First, we'll set up some state to allow us to locate the output
|
||||||
// index of the all the HTLC's within the commitment transaction. We
|
// index of the all the HTLC's within the commitment transaction. We
|
||||||
// must keep this index so we can validate the HTLC signatures sent to
|
// must keep this index so we can validate the HTLC signatures sent to
|
||||||
@ -608,8 +608,10 @@ func (c *commitment) populateHtlcIndexes() error {
|
|||||||
// populateIndex is a helper function that populates the necessary
|
// populateIndex is a helper function that populates the necessary
|
||||||
// indexes within the commitment view for a particular HTLC.
|
// indexes within the commitment view for a particular HTLC.
|
||||||
populateIndex := func(htlc *PaymentDescriptor, incoming bool) error {
|
populateIndex := func(htlc *PaymentDescriptor, incoming bool) error {
|
||||||
isDust := htlcIsDust(incoming, c.isOurs, c.feePerKw,
|
isDust := htlcIsDust(
|
||||||
htlc.Amount.ToSatoshis(), c.dustLimit)
|
chanType, incoming, c.isOurs, c.feePerKw,
|
||||||
|
htlc.Amount.ToSatoshis(), c.dustLimit,
|
||||||
|
)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
switch {
|
switch {
|
||||||
@ -782,8 +784,10 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
|||||||
// generate them in order to locate the outputs within the commitment
|
// generate them in order to locate the outputs within the commitment
|
||||||
// transaction. As we'll mark dust with a special output index in the
|
// transaction. As we'll mark dust with a special output index in the
|
||||||
// on-disk state snapshot.
|
// on-disk state snapshot.
|
||||||
isDustLocal := htlcIsDust(htlc.Incoming, true, feeRate,
|
isDustLocal := htlcIsDust(
|
||||||
htlc.Amt.ToSatoshis(), lc.channelState.LocalChanCfg.DustLimit)
|
chanType, htlc.Incoming, true, feeRate,
|
||||||
|
htlc.Amt.ToSatoshis(), lc.channelState.LocalChanCfg.DustLimit,
|
||||||
|
)
|
||||||
if !isDustLocal && localCommitKeys != nil {
|
if !isDustLocal && localCommitKeys != nil {
|
||||||
ourP2WSH, ourWitnessScript, err = genHtlcScript(
|
ourP2WSH, ourWitnessScript, err = genHtlcScript(
|
||||||
chanType, htlc.Incoming, true, htlc.RefundTimeout,
|
chanType, htlc.Incoming, true, htlc.RefundTimeout,
|
||||||
@ -793,8 +797,10 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
|||||||
return pd, err
|
return pd, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isDustRemote := htlcIsDust(htlc.Incoming, false, feeRate,
|
isDustRemote := htlcIsDust(
|
||||||
htlc.Amt.ToSatoshis(), lc.channelState.RemoteChanCfg.DustLimit)
|
chanType, htlc.Incoming, false, feeRate,
|
||||||
|
htlc.Amt.ToSatoshis(), lc.channelState.RemoteChanCfg.DustLimit,
|
||||||
|
)
|
||||||
if !isDustRemote && remoteCommitKeys != nil {
|
if !isDustRemote && remoteCommitKeys != nil {
|
||||||
theirP2WSH, theirWitnessScript, err = genHtlcScript(
|
theirP2WSH, theirWitnessScript, err = genHtlcScript(
|
||||||
chanType, htlc.Incoming, false, htlc.RefundTimeout,
|
chanType, htlc.Incoming, false, htlc.RefundTimeout,
|
||||||
@ -930,7 +936,8 @@ func (lc *LightningChannel) diskCommitToMemCommit(isLocal bool,
|
|||||||
|
|
||||||
// Finally, we'll re-populate the HTLC index for this state so we can
|
// Finally, we'll re-populate the HTLC index for this state so we can
|
||||||
// properly locate each HTLC within the commitment transaction.
|
// properly locate each HTLC within the commitment transaction.
|
||||||
if err := commit.populateHtlcIndexes(); err != nil {
|
err = commit.populateHtlcIndexes(lc.channelState.ChanType)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1410,8 +1417,10 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||||||
pd.OnionBlob = make([]byte, len(wireMsg.OnionBlob))
|
pd.OnionBlob = make([]byte, len(wireMsg.OnionBlob))
|
||||||
copy(pd.OnionBlob[:], wireMsg.OnionBlob[:])
|
copy(pd.OnionBlob[:], wireMsg.OnionBlob[:])
|
||||||
|
|
||||||
isDustRemote := htlcIsDust(false, false, feeRate,
|
isDustRemote := htlcIsDust(
|
||||||
wireMsg.Amount.ToSatoshis(), remoteDustLimit)
|
lc.channelState.ChanType, false, false, feeRate,
|
||||||
|
wireMsg.Amount.ToSatoshis(), remoteDustLimit,
|
||||||
|
)
|
||||||
if !isDustRemote {
|
if !isDustRemote {
|
||||||
theirP2WSH, theirWitnessScript, err := genHtlcScript(
|
theirP2WSH, theirWitnessScript, err := genHtlcScript(
|
||||||
lc.channelState.ChanType, false, false,
|
lc.channelState.ChanType, false, false,
|
||||||
@ -2168,7 +2177,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// If the HTLC is dust, then we'll skip it as it doesn't have
|
// If the HTLC is dust, then we'll skip it as it doesn't have
|
||||||
// an output on the commitment transaction.
|
// an output on the commitment transaction.
|
||||||
if htlcIsDust(
|
if htlcIsDust(
|
||||||
htlc.Incoming, false,
|
chanState.ChanType, htlc.Incoming, false,
|
||||||
chainfee.SatPerKWeight(revokedSnapshot.FeePerKw),
|
chainfee.SatPerKWeight(revokedSnapshot.FeePerKw),
|
||||||
htlc.Amt.ToSatoshis(), chanState.RemoteChanCfg.DustLimit,
|
htlc.Amt.ToSatoshis(), chanState.RemoteChanCfg.DustLimit,
|
||||||
) {
|
) {
|
||||||
@ -2239,25 +2248,14 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// htlcTimeoutFee returns the fee in satoshis required for an HTLC timeout
|
|
||||||
// transaction based on the current fee rate.
|
|
||||||
func htlcTimeoutFee(feePerKw chainfee.SatPerKWeight) btcutil.Amount {
|
|
||||||
return feePerKw.FeeForWeight(input.HtlcTimeoutWeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
// htlcSuccessFee returns the fee in satoshis required for an HTLC success
|
|
||||||
// transaction based on the current fee rate.
|
|
||||||
func htlcSuccessFee(feePerKw chainfee.SatPerKWeight) btcutil.Amount {
|
|
||||||
return feePerKw.FeeForWeight(input.HtlcSuccessWeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
// htlcIsDust determines if an HTLC output is dust or not depending on two
|
// htlcIsDust determines if an HTLC output is dust or not depending on two
|
||||||
// bits: if the HTLC is incoming and if the HTLC will be placed on our
|
// bits: if the HTLC is incoming and if the HTLC will be placed on our
|
||||||
// commitment transaction, or theirs. These two pieces of information are
|
// commitment transaction, or theirs. These two pieces of information are
|
||||||
// require as we currently used second-level HTLC transactions as off-chain
|
// require as we currently used second-level HTLC transactions as off-chain
|
||||||
// covenants. Depending on the two bits, we'll either be using a timeout or
|
// covenants. Depending on the two bits, we'll either be using a timeout or
|
||||||
// success transaction which have different weights.
|
// success transaction which have different weights.
|
||||||
func htlcIsDust(incoming, ourCommit bool, feePerKw chainfee.SatPerKWeight,
|
func htlcIsDust(chanType channeldb.ChannelType,
|
||||||
|
incoming, ourCommit bool, feePerKw chainfee.SatPerKWeight,
|
||||||
htlcAmt, dustLimit btcutil.Amount) bool {
|
htlcAmt, dustLimit btcutil.Amount) bool {
|
||||||
|
|
||||||
// First we'll determine the fee required for this HTLC based on if this is
|
// First we'll determine the fee required for this HTLC based on if this is
|
||||||
@ -2269,25 +2267,25 @@ func htlcIsDust(incoming, ourCommit bool, feePerKw chainfee.SatPerKWeight,
|
|||||||
// If this is an incoming HTLC on our commitment transaction, then the
|
// If this is an incoming HTLC on our commitment transaction, then the
|
||||||
// second-level transaction will be a success transaction.
|
// second-level transaction will be a success transaction.
|
||||||
case incoming && ourCommit:
|
case incoming && ourCommit:
|
||||||
htlcFee = htlcSuccessFee(feePerKw)
|
htlcFee = HtlcSuccessFee(chanType, feePerKw)
|
||||||
|
|
||||||
// If this is an incoming HTLC on their commitment transaction, then
|
// If this is an incoming HTLC on their commitment transaction, then
|
||||||
// we'll be using a second-level timeout transaction as they've added
|
// we'll be using a second-level timeout transaction as they've added
|
||||||
// this HTLC.
|
// this HTLC.
|
||||||
case incoming && !ourCommit:
|
case incoming && !ourCommit:
|
||||||
htlcFee = htlcTimeoutFee(feePerKw)
|
htlcFee = HtlcTimeoutFee(chanType, feePerKw)
|
||||||
|
|
||||||
// If this is an outgoing HTLC on our commitment transaction, then
|
// If this is an outgoing HTLC on our commitment transaction, then
|
||||||
// we'll be using a timeout transaction as we're the sender of the
|
// we'll be using a timeout transaction as we're the sender of the
|
||||||
// HTLC.
|
// HTLC.
|
||||||
case !incoming && ourCommit:
|
case !incoming && ourCommit:
|
||||||
htlcFee = htlcTimeoutFee(feePerKw)
|
htlcFee = HtlcTimeoutFee(chanType, feePerKw)
|
||||||
|
|
||||||
// If this is an outgoing HTLC on their commitment transaction, then
|
// If this is an outgoing HTLC on their commitment transaction, then
|
||||||
// we'll be using an HTLC success transaction as they're the receiver
|
// we'll be using an HTLC success transaction as they're the receiver
|
||||||
// of this HTLC.
|
// of this HTLC.
|
||||||
case !incoming && !ourCommit:
|
case !incoming && !ourCommit:
|
||||||
htlcFee = htlcSuccessFee(feePerKw)
|
htlcFee = HtlcSuccessFee(chanType, feePerKw)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (htlcAmt - htlcFee) < dustLimit
|
return (htlcAmt - htlcFee) < dustLimit
|
||||||
@ -2431,7 +2429,7 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
|||||||
|
|
||||||
// Finally, we'll populate all the HTLC indexes so we can track the
|
// Finally, we'll populate all the HTLC indexes so we can track the
|
||||||
// locations of each HTLC in the commitment state.
|
// locations of each HTLC in the commitment state.
|
||||||
if err := c.populateHtlcIndexes(); err != nil {
|
if err := c.populateHtlcIndexes(lc.channelState.ChanType); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2769,8 +2767,10 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
|||||||
// dust output after taking into account second-level HTLC fees, then a
|
// dust output after taking into account second-level HTLC fees, then a
|
||||||
// sigJob will be generated and appended to the current batch.
|
// sigJob will be generated and appended to the current batch.
|
||||||
for _, htlc := range remoteCommitView.incomingHTLCs {
|
for _, htlc := range remoteCommitView.incomingHTLCs {
|
||||||
if htlcIsDust(true, false, feePerKw, htlc.Amount.ToSatoshis(),
|
if htlcIsDust(
|
||||||
dustLimit) {
|
chanType, true, false, feePerKw,
|
||||||
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2785,7 +2785,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
|||||||
// HTLC timeout transaction for them. The output of the timeout
|
// HTLC timeout transaction for them. The output of the timeout
|
||||||
// transaction needs to account for fees, so we'll compute the
|
// transaction needs to account for fees, so we'll compute the
|
||||||
// required fee and output now.
|
// required fee and output now.
|
||||||
htlcFee := htlcTimeoutFee(feePerKw)
|
htlcFee := HtlcTimeoutFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
// With the fee calculate, we can properly create the HTLC
|
// With the fee calculate, we can properly create the HTLC
|
||||||
@ -2822,8 +2822,10 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
|||||||
sigBatch = append(sigBatch, sigJob)
|
sigBatch = append(sigBatch, sigJob)
|
||||||
}
|
}
|
||||||
for _, htlc := range remoteCommitView.outgoingHTLCs {
|
for _, htlc := range remoteCommitView.outgoingHTLCs {
|
||||||
if htlcIsDust(false, false, feePerKw, htlc.Amount.ToSatoshis(),
|
if htlcIsDust(
|
||||||
dustLimit) {
|
chanType, false, false, feePerKw,
|
||||||
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2836,7 +2838,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
|||||||
// HTLC success transaction for them. The output of the timeout
|
// HTLC success transaction for them. The output of the timeout
|
||||||
// transaction needs to account for fees, so we'll compute the
|
// transaction needs to account for fees, so we'll compute the
|
||||||
// required fee and output now.
|
// required fee and output now.
|
||||||
htlcFee := htlcSuccessFee(feePerKw)
|
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
// With the proper output amount calculated, we can now
|
// With the proper output amount calculated, we can now
|
||||||
@ -3785,16 +3787,20 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool,
|
|||||||
// weight, needed to calculate the transaction fee.
|
// weight, needed to calculate the transaction fee.
|
||||||
var totalHtlcWeight int64
|
var totalHtlcWeight int64
|
||||||
for _, htlc := range filteredHTLCView.ourUpdates {
|
for _, htlc := range filteredHTLCView.ourUpdates {
|
||||||
if htlcIsDust(remoteChain, !remoteChain, feePerKw,
|
if htlcIsDust(
|
||||||
htlc.Amount.ToSatoshis(), dustLimit) {
|
lc.channelState.ChanType, remoteChain, !remoteChain,
|
||||||
|
feePerKw, htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
totalHtlcWeight += input.HTLCWeight
|
totalHtlcWeight += input.HTLCWeight
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.theirUpdates {
|
for _, htlc := range filteredHTLCView.theirUpdates {
|
||||||
if htlcIsDust(!remoteChain, !remoteChain, feePerKw,
|
if htlcIsDust(
|
||||||
htlc.Amount.ToSatoshis(), dustLimit) {
|
lc.channelState.ChanType, !remoteChain, !remoteChain,
|
||||||
|
feePerKw, htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3857,7 +3863,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
|||||||
Index: uint32(htlc.localOutputIndex),
|
Index: uint32(htlc.localOutputIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
htlcFee := htlcSuccessFee(feePerKw)
|
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
successTx, err := createHtlcSuccessTx(
|
successTx, err := createHtlcSuccessTx(
|
||||||
@ -3911,7 +3917,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
|||||||
Index: uint32(htlc.localOutputIndex),
|
Index: uint32(htlc.localOutputIndex),
|
||||||
}
|
}
|
||||||
|
|
||||||
htlcFee := htlcTimeoutFee(feePerKw)
|
htlcFee := HtlcTimeoutFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
timeoutTx, err := createHtlcTimeoutTx(
|
timeoutTx, err := createHtlcTimeoutTx(
|
||||||
@ -5383,7 +5389,7 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||||||
// In order to properly reconstruct the HTLC transaction, we'll need to
|
// In order to properly reconstruct the HTLC transaction, we'll need to
|
||||||
// re-calculate the fee required at this state, so we can add the
|
// re-calculate the fee required at this state, so we can add the
|
||||||
// correct output value amount to the transaction.
|
// correct output value amount to the transaction.
|
||||||
htlcFee := htlcTimeoutFee(feePerKw)
|
htlcFee := HtlcTimeoutFee(chanType, feePerKw)
|
||||||
secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee
|
secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
// With the fee calculated, re-construct the second level timeout
|
// With the fee calculated, re-construct the second level timeout
|
||||||
@ -5513,7 +5519,7 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||||||
|
|
||||||
// First, we'll reconstruct the original HTLC success transaction,
|
// First, we'll reconstruct the original HTLC success transaction,
|
||||||
// taking into account the fee rate used.
|
// taking into account the fee rate used.
|
||||||
htlcFee := htlcSuccessFee(feePerKw)
|
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
||||||
secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee
|
secondLevelOutputAmt := htlc.Amt.ToSatoshis() - htlcFee
|
||||||
successTx, err := createHtlcSuccessTx(
|
successTx, err := createHtlcSuccessTx(
|
||||||
chanType, op, secondLevelOutputAmt, csvDelay,
|
chanType, op, secondLevelOutputAmt, csvDelay,
|
||||||
@ -5637,8 +5643,10 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool,
|
|||||||
// We'll skip any HTLC's which were dust on the commitment
|
// We'll skip any HTLC's which were dust on the commitment
|
||||||
// transaction, as these don't have a corresponding output
|
// transaction, as these don't have a corresponding output
|
||||||
// within the commitment transaction.
|
// within the commitment transaction.
|
||||||
if htlcIsDust(htlc.Incoming, ourCommit, feePerKw,
|
if htlcIsDust(
|
||||||
htlc.Amt.ToSatoshis(), dustLimit) {
|
chanType, htlc.Incoming, ourCommit, feePerKw,
|
||||||
|
htlc.Amt.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6141,7 +6149,7 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView,
|
|||||||
// For an extra HTLC fee to be paid on our commitment, the HTLC must be
|
// For an extra HTLC fee to be paid on our commitment, the HTLC must be
|
||||||
// large enough to make a non-dust HTLC timeout transaction.
|
// large enough to make a non-dust HTLC timeout transaction.
|
||||||
htlcFee := lnwire.NewMSatFromSatoshis(
|
htlcFee := lnwire.NewMSatFromSatoshis(
|
||||||
htlcTimeoutFee(feePerKw),
|
HtlcTimeoutFee(lc.channelState.ChanType, feePerKw),
|
||||||
)
|
)
|
||||||
|
|
||||||
// If we are looking at the remote commitment, we must use the remote
|
// If we are looking at the remote commitment, we must use the remote
|
||||||
@ -6151,7 +6159,7 @@ func (lc *LightningChannel) availableCommitmentBalance(view *htlcView,
|
|||||||
lc.channelState.RemoteChanCfg.DustLimit,
|
lc.channelState.RemoteChanCfg.DustLimit,
|
||||||
)
|
)
|
||||||
htlcFee = lnwire.NewMSatFromSatoshis(
|
htlcFee = lnwire.NewMSatFromSatoshis(
|
||||||
htlcSuccessFee(feePerKw),
|
HtlcSuccessFee(lc.channelState.ChanType, feePerKw),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,7 +1011,8 @@ func TestHTLCDustLimit(t *testing.T) {
|
|||||||
|
|
||||||
// The amount of the HTLC should be above Alice's dust limit and below
|
// The amount of the HTLC should be above Alice's dust limit and below
|
||||||
// Bob's dust limit.
|
// Bob's dust limit.
|
||||||
htlcSat := (btcutil.Amount(500) + htlcTimeoutFee(
|
htlcSat := (btcutil.Amount(500) + HtlcTimeoutFee(
|
||||||
|
aliceChannel.channelState.ChanType,
|
||||||
chainfee.SatPerKWeight(
|
chainfee.SatPerKWeight(
|
||||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||||
),
|
),
|
||||||
@ -1119,8 +1120,12 @@ func TestHTLCSigNumber(t *testing.T) {
|
|||||||
t.Fatalf("unable to get fee: %v", err)
|
t.Fatalf("unable to get fee: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
belowDust := btcutil.Amount(500) + htlcTimeoutFee(feePerKw)
|
belowDust := btcutil.Amount(500) + HtlcTimeoutFee(
|
||||||
aboveDust := btcutil.Amount(1400) + htlcSuccessFee(feePerKw)
|
channeldb.SingleFunderTweaklessBit, feePerKw,
|
||||||
|
)
|
||||||
|
aboveDust := btcutil.Amount(1400) + HtlcSuccessFee(
|
||||||
|
channeldb.SingleFunderTweaklessBit, feePerKw,
|
||||||
|
)
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// Test that Bob will reject a commitment if Alice doesn't send enough
|
// Test that Bob will reject a commitment if Alice doesn't send enough
|
||||||
@ -1278,7 +1283,8 @@ func TestChannelBalanceDustLimit(t *testing.T) {
|
|||||||
defaultFee := calcStaticFee(1)
|
defaultFee := calcStaticFee(1)
|
||||||
aliceBalance := aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis()
|
aliceBalance := aliceChannel.channelState.LocalCommitment.LocalBalance.ToSatoshis()
|
||||||
htlcSat := aliceBalance - defaultFee
|
htlcSat := aliceBalance - defaultFee
|
||||||
htlcSat += htlcSuccessFee(
|
htlcSat += HtlcSuccessFee(
|
||||||
|
aliceChannel.channelState.ChanType,
|
||||||
chainfee.SatPerKWeight(
|
chainfee.SatPerKWeight(
|
||||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||||
),
|
),
|
||||||
@ -4759,10 +4765,10 @@ func TestChanAvailableBalanceNearHtlcFee(t *testing.T) {
|
|||||||
aliceChannel.channelState.LocalCommitment.CommitFee,
|
aliceChannel.channelState.LocalCommitment.CommitFee,
|
||||||
)
|
)
|
||||||
htlcTimeoutFee := lnwire.NewMSatFromSatoshis(
|
htlcTimeoutFee := lnwire.NewMSatFromSatoshis(
|
||||||
htlcTimeoutFee(feeRate),
|
HtlcTimeoutFee(aliceChannel.channelState.ChanType, feeRate),
|
||||||
)
|
)
|
||||||
htlcSuccessFee := lnwire.NewMSatFromSatoshis(
|
htlcSuccessFee := lnwire.NewMSatFromSatoshis(
|
||||||
htlcSuccessFee(feeRate),
|
HtlcSuccessFee(aliceChannel.channelState.ChanType, feeRate),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Helper method to check the current reported balance.
|
// Helper method to check the current reported balance.
|
||||||
@ -6273,7 +6279,8 @@ func TestChanReserveLocalInitiatorDustHtlc(t *testing.T) {
|
|||||||
// limit (1300 sat). It is considered dust if the amount remaining
|
// limit (1300 sat). It is considered dust if the amount remaining
|
||||||
// after paying the HTLC fee is below the dustlimit, so we choose a
|
// after paying the HTLC fee is below the dustlimit, so we choose a
|
||||||
// size of 500+htlcFee.
|
// size of 500+htlcFee.
|
||||||
htlcSat := btcutil.Amount(500) + htlcTimeoutFee(
|
htlcSat := btcutil.Amount(500) + HtlcTimeoutFee(
|
||||||
|
aliceChannel.channelState.ChanType,
|
||||||
chainfee.SatPerKWeight(
|
chainfee.SatPerKWeight(
|
||||||
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
aliceChannel.channelState.LocalCommitment.FeePerKw,
|
||||||
),
|
),
|
||||||
|
@ -255,6 +255,29 @@ func CommitWeight(chanType channeldb.ChannelType) int64 {
|
|||||||
return input.CommitWeight
|
return input.CommitWeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HtlcTimeoutFee returns the fee in satoshis required for an HTLC timeout
|
||||||
|
// transaction based on the current fee rate.
|
||||||
|
func HtlcTimeoutFee(chanType channeldb.ChannelType,
|
||||||
|
feePerKw chainfee.SatPerKWeight) btcutil.Amount {
|
||||||
|
|
||||||
|
if chanType.HasAnchors() {
|
||||||
|
return feePerKw.FeeForWeight(input.HtlcTimeoutWeightConfirmed)
|
||||||
|
}
|
||||||
|
|
||||||
|
return feePerKw.FeeForWeight(input.HtlcTimeoutWeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HtlcSuccessFee returns the fee in satoshis required for an HTLC success
|
||||||
|
// transaction based on the current fee rate.
|
||||||
|
func HtlcSuccessFee(chanType channeldb.ChannelType,
|
||||||
|
feePerKw chainfee.SatPerKWeight) btcutil.Amount {
|
||||||
|
|
||||||
|
if chanType.HasAnchors() {
|
||||||
|
return feePerKw.FeeForWeight(input.HtlcSuccessWeightConfirmed)
|
||||||
|
}
|
||||||
|
return feePerKw.FeeForWeight(input.HtlcSuccessWeight)
|
||||||
|
}
|
||||||
|
|
||||||
// CommitScriptAnchors return the scripts to use for the local and remote
|
// CommitScriptAnchors return the scripts to use for the local and remote
|
||||||
// anchor.
|
// anchor.
|
||||||
func CommitScriptAnchors(localChanCfg,
|
func CommitScriptAnchors(localChanCfg,
|
||||||
@ -373,18 +396,20 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
|||||||
|
|
||||||
numHTLCs := int64(0)
|
numHTLCs := int64(0)
|
||||||
for _, htlc := range filteredHTLCView.ourUpdates {
|
for _, htlc := range filteredHTLCView.ourUpdates {
|
||||||
if htlcIsDust(false, isOurs, feePerKw,
|
if htlcIsDust(
|
||||||
htlc.Amount.ToSatoshis(), dustLimit) {
|
cb.chanState.ChanType, false, isOurs, feePerKw,
|
||||||
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
numHTLCs++
|
numHTLCs++
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.theirUpdates {
|
for _, htlc := range filteredHTLCView.theirUpdates {
|
||||||
if htlcIsDust(true, isOurs, feePerKw,
|
if htlcIsDust(
|
||||||
htlc.Amount.ToSatoshis(), dustLimit) {
|
cb.chanState.ChanType, true, isOurs, feePerKw,
|
||||||
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,8 +485,10 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
|||||||
// purposes of sorting.
|
// purposes of sorting.
|
||||||
cltvs := make([]uint32, len(commitTx.TxOut))
|
cltvs := make([]uint32, len(commitTx.TxOut))
|
||||||
for _, htlc := range filteredHTLCView.ourUpdates {
|
for _, htlc := range filteredHTLCView.ourUpdates {
|
||||||
if htlcIsDust(false, isOurs, feePerKw,
|
if htlcIsDust(
|
||||||
htlc.Amount.ToSatoshis(), dustLimit) {
|
cb.chanState.ChanType, false, isOurs, feePerKw,
|
||||||
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,8 +502,10 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
|||||||
cltvs = append(cltvs, htlc.Timeout)
|
cltvs = append(cltvs, htlc.Timeout)
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.theirUpdates {
|
for _, htlc := range filteredHTLCView.theirUpdates {
|
||||||
if htlcIsDust(true, isOurs, feePerKw,
|
if htlcIsDust(
|
||||||
htlc.Amount.ToSatoshis(), dustLimit) {
|
cb.chanState.ChanType, true, isOurs, feePerKw,
|
||||||
|
htlc.Amount.ToSatoshis(), dustLimit,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user