lnwallet: apply dust HTLC amounts to fees
If an HTLC’s value is below a node’s dust limit, the amount for that HTLC should be applied to to the fee used for the channel’s commitment transaction.
This commit is contained in:
parent
497b522c13
commit
5068541044
@ -1307,7 +1307,7 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
|||||||
// * tally in separate accumulator, subtract from fee amount
|
// * tally in separate accumulator, subtract from fee amount
|
||||||
// * when dumping fees back into initiator output, only dumb explicit
|
// * when dumping fees back into initiator output, only dumb explicit
|
||||||
// fee
|
// fee
|
||||||
var dustLimit btcutil.Amount
|
var dustLimit, dustFees btcutil.Amount
|
||||||
if remoteChain {
|
if remoteChain {
|
||||||
dustLimit = lc.channelState.TheirDustLimit
|
dustLimit = lc.channelState.TheirDustLimit
|
||||||
} else {
|
} else {
|
||||||
@ -1316,12 +1316,14 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
|||||||
numHTLCs := 0
|
numHTLCs := 0
|
||||||
for _, htlc := range filteredHTLCView.ourUpdates {
|
for _, htlc := range filteredHTLCView.ourUpdates {
|
||||||
if htlc.Amount < dustLimit {
|
if htlc.Amount < dustLimit {
|
||||||
|
dustFees += htlc.Amount
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
numHTLCs++
|
numHTLCs++
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.theirUpdates {
|
for _, htlc := range filteredHTLCView.theirUpdates {
|
||||||
if htlc.Amount < dustLimit {
|
if htlc.Amount < dustLimit {
|
||||||
|
dustFees += htlc.Amount
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
numHTLCs++
|
numHTLCs++
|
||||||
@ -1332,7 +1334,8 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
|||||||
// by the current fee-per-kw, then divide by 1000 to get the proper
|
// by the current fee-per-kw, then divide by 1000 to get the proper
|
||||||
// fee.
|
// fee.
|
||||||
totalCommitWeight := commitWeight + btcutil.Amount(htlcWeight*numHTLCs)
|
totalCommitWeight := commitWeight + btcutil.Amount(htlcWeight*numHTLCs)
|
||||||
commitFee := (lc.channelState.FeePerKw * totalCommitWeight) / 1000
|
commitFee := lc.channelState.FeePerKw * totalCommitWeight / 1000
|
||||||
|
commitFee -= dustFees
|
||||||
|
|
||||||
// Currently, within the protocol, the initiator always pays the fees.
|
// Currently, within the protocol, the initiator always pays the fees.
|
||||||
// So we'll subtract the fee amount from the balance of the current
|
// So we'll subtract the fee amount from the balance of the current
|
||||||
|
@ -932,6 +932,60 @@ func TestForceClose(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestDustHTLCFees checks that fees are calculated correctly when HTLCs fall
|
||||||
|
// below the nodes' dust limit. In these cases, the amount of the dust HTLCs
|
||||||
|
// should be applied to the commitment transaction fee.
|
||||||
|
func TestDustHTLCFees(t *testing.T) {
|
||||||
|
createHTLC := func(data, amount btcutil.Amount) (*lnwire.UpdateAddHTLC,
|
||||||
|
[32]byte) {
|
||||||
|
preimage := bytes.Repeat([]byte{byte(data)}, 32)
|
||||||
|
paymentHash := sha256.Sum256(preimage)
|
||||||
|
|
||||||
|
var returnPreimage [32]byte
|
||||||
|
copy(returnPreimage[:], preimage)
|
||||||
|
|
||||||
|
return &lnwire.UpdateAddHTLC{
|
||||||
|
PaymentHash: paymentHash,
|
||||||
|
Amount: amount,
|
||||||
|
Expiry: uint32(5),
|
||||||
|
}, returnPreimage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a test channel which will be used for the duration of this
|
||||||
|
// unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||||
|
// and Bob having 5 BTC.
|
||||||
|
aliceChannel, bobChannel, cleanUp, err := createTestChannels(3)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create test channels: %v", err)
|
||||||
|
}
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
// This HTLC amount should be lower than the dust limits of both nodes.
|
||||||
|
htlcAmount := btcutil.Amount(100)
|
||||||
|
htlc, _ := createHTLC(0, htlcAmount)
|
||||||
|
if _, err := aliceChannel.AddHTLC(htlc); err != nil {
|
||||||
|
t.Fatalf("alice unable to add htlc: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := bobChannel.ReceiveHTLC(htlc); err != nil {
|
||||||
|
t.Fatalf("bob unable to receive htlc: %v", err)
|
||||||
|
}
|
||||||
|
if err := forceStateTransition(aliceChannel, bobChannel); err != nil {
|
||||||
|
t.Fatalf("Can't update the channel state: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultFee := calcStaticFee(0)
|
||||||
|
if aliceChannel.channelState.CommitFee != defaultFee-htlcAmount {
|
||||||
|
t.Fatalf("dust htlc amounts not subtracted from commitment fee "+
|
||||||
|
"expected %v, got %v", defaultFee-htlcAmount,
|
||||||
|
aliceChannel.channelState.CommitFee)
|
||||||
|
}
|
||||||
|
if bobChannel.channelState.CommitFee != defaultFee-htlcAmount {
|
||||||
|
t.Fatalf("dust htlc amounts not subtracted from commitment fee "+
|
||||||
|
"expected %v, got %v", defaultFee-htlcAmount,
|
||||||
|
bobChannel.channelState.CommitFee)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestCheckDustLimit checks that unsettled HTLC with dust limit not included in
|
// TestCheckDustLimit checks that unsettled HTLC with dust limit not included in
|
||||||
// commitment transaction as output, but sender balance is decreased (thereby all
|
// commitment transaction as output, but sender balance is decreased (thereby all
|
||||||
// unsettled dust HTLCs will go to miners fee).
|
// unsettled dust HTLCs will go to miners fee).
|
||||||
|
Loading…
Reference in New Issue
Block a user