lnwallet: when calc'ing fee for commitment tx, use current fee-per-kw
This commit modifies the fee calculation logic when creating or accepting a new commitment transaction to use the set FeePerKw within the channel rather then re-query the estimator each time. The prior behavior was benign as we currently use a static fee estimator, but the dynamic setting this could’ve caused a state divergence.
This commit is contained in:
parent
82f591dbab
commit
e689ef61dd
@ -1256,10 +1256,8 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
|||||||
commitChain = lc.localCommitChain
|
commitChain = lc.localCommitChain
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): don't assume view is always fetched from tip?
|
ourBalance := commitChain.tip().ourBalance
|
||||||
var ourBalance, theirBalance btcutil.Amount
|
theirBalance := commitChain.tip().theirBalance
|
||||||
ourBalance = commitChain.tip().ourBalance
|
|
||||||
theirBalance = commitChain.tip().theirBalance
|
|
||||||
|
|
||||||
// Add the fee from the previous commitment state back to the
|
// Add the fee from the previous commitment state back to the
|
||||||
// initiator's balance, so that the fee can be recalculated and
|
// initiator's balance, so that the fee can be recalculated and
|
||||||
@ -1307,20 +1305,28 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
|||||||
numHTLCs++
|
numHTLCs++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the fee for the commitment transaction based on its size.
|
// Next, we'll calculate the fee for the commitment transaction based
|
||||||
commitFee := btcutil.Amount(lc.feeEstimator.EstimateFeePerWeight(1)) *
|
// on its total weight. Once we have the total weight, we'll multiply
|
||||||
(commitWeight + btcutil.Amount(htlcWeight*numHTLCs)) / 1000
|
// by the current fee-per-kw, then divide by 1000 to get the proper
|
||||||
|
// fee.
|
||||||
|
totalCommitWeight := commitWeight + btcutil.Amount(htlcWeight*numHTLCs)
|
||||||
|
commitFee := (lc.channelState.FeePerKw * totalCommitWeight) / 1000
|
||||||
|
|
||||||
|
// Currently, within the protocol, the initiator always pays the fees.
|
||||||
|
// So we'll subtract the fee amount from the balance of the current
|
||||||
|
// initiator.
|
||||||
if lc.channelState.IsInitiator {
|
if lc.channelState.IsInitiator {
|
||||||
ourBalance = ourBalance - commitFee
|
ourBalance = ourBalance - commitFee
|
||||||
} else if !lc.channelState.IsInitiator {
|
} else if !lc.channelState.IsInitiator {
|
||||||
theirBalance = theirBalance - commitFee
|
theirBalance = theirBalance - commitFee
|
||||||
}
|
}
|
||||||
|
|
||||||
var selfKey *btcec.PublicKey
|
var (
|
||||||
var remoteKey *btcec.PublicKey
|
selfKey *btcec.PublicKey
|
||||||
var delay uint32
|
remoteKey *btcec.PublicKey
|
||||||
var delayBalance, p2wkhBalance btcutil.Amount
|
delay uint32
|
||||||
|
delayBalance, p2wkhBalance btcutil.Amount
|
||||||
|
)
|
||||||
if remoteChain {
|
if remoteChain {
|
||||||
selfKey = lc.channelState.TheirCommitKey
|
selfKey = lc.channelState.TheirCommitKey
|
||||||
remoteKey = lc.channelState.OurCommitKey
|
remoteKey = lc.channelState.OurCommitKey
|
||||||
@ -2542,8 +2548,7 @@ func (lc *LightningChannel) InitCooperativeClose() ([]byte, *chainhash.Hash, err
|
|||||||
|
|
||||||
// Calculate the fee for the commitment transaction based on its size.
|
// Calculate the fee for the commitment transaction based on its size.
|
||||||
// For a cooperative close, there should be no HTLCs.
|
// For a cooperative close, there should be no HTLCs.
|
||||||
commitFee := btcutil.Amount(lc.feeEstimator.EstimateFeePerWeight(1)) *
|
commitFee := (lc.channelState.FeePerKw * commitWeight) / 1000
|
||||||
commitWeight / 1000
|
|
||||||
|
|
||||||
if lc.channelState.IsInitiator {
|
if lc.channelState.IsInitiator {
|
||||||
lc.channelState.OurBalance = lc.channelState.OurBalance - commitFee
|
lc.channelState.OurBalance = lc.channelState.OurBalance - commitFee
|
||||||
@ -2603,8 +2608,8 @@ func (lc *LightningChannel) CompleteCooperativeClose(remoteSig []byte) (*wire.Ms
|
|||||||
|
|
||||||
// Calculate the fee for the commitment transaction based on its size.
|
// Calculate the fee for the commitment transaction based on its size.
|
||||||
// For a cooperative close, there should be no HTLCs.
|
// For a cooperative close, there should be no HTLCs.
|
||||||
commitFee := btcutil.Amount(lc.feeEstimator.EstimateFeePerWeight(1)) *
|
// TODO(roasbeef): should be using fee passed in
|
||||||
commitWeight / 1000
|
commitFee := (lc.channelState.FeePerKw * commitWeight) / 1000
|
||||||
|
|
||||||
if lc.channelState.IsInitiator {
|
if lc.channelState.IsInitiator {
|
||||||
lc.channelState.OurBalance = lc.channelState.OurBalance - commitFee
|
lc.channelState.OurBalance = lc.channelState.OurBalance - commitFee
|
||||||
|
@ -186,7 +186,7 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
|
|||||||
channelCapacity := btcutil.Amount(10 * 1e8)
|
channelCapacity := btcutil.Amount(10 * 1e8)
|
||||||
channelBal := channelCapacity / 2
|
channelBal := channelCapacity / 2
|
||||||
aliceDustLimit := btcutil.Amount(200)
|
aliceDustLimit := btcutil.Amount(200)
|
||||||
bobDustLimit := btcutil.Amount(800)
|
bobDustLimit := btcutil.Amount(1300)
|
||||||
csvTimeoutAlice := uint32(5)
|
csvTimeoutAlice := uint32(5)
|
||||||
csvTimeoutBob := uint32(4)
|
csvTimeoutBob := uint32(4)
|
||||||
|
|
||||||
@ -244,10 +244,12 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
|
|||||||
var obsfucator [StateHintSize]byte
|
var obsfucator [StateHintSize]byte
|
||||||
copy(obsfucator[:], aliceFirstRevoke[:])
|
copy(obsfucator[:], aliceFirstRevoke[:])
|
||||||
|
|
||||||
|
feePerKw := btcutil.Amount(6000)
|
||||||
aliceChannelState := &channeldb.OpenChannel{
|
aliceChannelState := &channeldb.OpenChannel{
|
||||||
IdentityPub: aliceKeyPub,
|
IdentityPub: aliceKeyPub,
|
||||||
ChanID: prevOut,
|
ChanID: prevOut,
|
||||||
ChanType: channeldb.SingleFunder,
|
ChanType: channeldb.SingleFunder,
|
||||||
|
FeePerKw: feePerKw,
|
||||||
IsInitiator: true,
|
IsInitiator: true,
|
||||||
StateHintObsfucator: obsfucator,
|
StateHintObsfucator: obsfucator,
|
||||||
OurCommitKey: aliceKeyPub,
|
OurCommitKey: aliceKeyPub,
|
||||||
@ -272,6 +274,7 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
|
|||||||
}
|
}
|
||||||
bobChannelState := &channeldb.OpenChannel{
|
bobChannelState := &channeldb.OpenChannel{
|
||||||
IdentityPub: bobKeyPub,
|
IdentityPub: bobKeyPub,
|
||||||
|
FeePerKw: feePerKw,
|
||||||
ChanID: prevOut,
|
ChanID: prevOut,
|
||||||
ChanType: channeldb.SingleFunder,
|
ChanType: channeldb.SingleFunder,
|
||||||
IsInitiator: false,
|
IsInitiator: false,
|
||||||
@ -306,7 +309,7 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
|
|||||||
bobSigner := &mockSigner{bobKeyPriv}
|
bobSigner := &mockSigner{bobKeyPriv}
|
||||||
|
|
||||||
notifier := &mockNotfier{}
|
notifier := &mockNotfier{}
|
||||||
estimator := &StaticFeeEstimator{50, 6}
|
estimator := &StaticFeeEstimator{24, 6}
|
||||||
|
|
||||||
channelAlice, err := NewLightningChannel(aliceSigner, notifier,
|
channelAlice, err := NewLightningChannel(aliceSigner, notifier,
|
||||||
estimator, aliceChannelState)
|
estimator, aliceChannelState)
|
||||||
@ -614,7 +617,7 @@ func TestCheckCommitTxSize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actualCost := blockchain.GetTransactionWeight(btcutil.NewTx(commitTx))
|
actualCost := blockchain.GetTransactionWeight(btcutil.NewTx(commitTx))
|
||||||
estimatedCost := estimateCommitTxCost(count, false)
|
estimatedCost := estimateCommitTxWeight(count, false)
|
||||||
|
|
||||||
diff := int(estimatedCost - actualCost)
|
diff := int(estimatedCost - actualCost)
|
||||||
if 0 > diff || BaseCommitmentTxSizeEstimationError < diff {
|
if 0 > diff || BaseCommitmentTxSizeEstimationError < diff {
|
||||||
@ -1143,9 +1146,10 @@ func TestCheckDustLimit(t *testing.T) {
|
|||||||
// transaction is below the dust limit. We create an HTLC that will
|
// transaction is below the dust limit. We create an HTLC that will
|
||||||
// only leave a small enough amount to Alice such that Bob will
|
// only leave a small enough amount to Alice such that Bob will
|
||||||
// consider it a dust output.
|
// consider it a dust output.
|
||||||
|
// TODO(roasbeef): test needs to be fixed after reserves and proper
|
||||||
|
// rolling over of dust into fees is done
|
||||||
aliceAmount := btcutil.Amount(5e8)
|
aliceAmount := btcutil.Amount(5e8)
|
||||||
htlcAmount2 := aliceAmount - btcutil.Amount(1000)
|
htlcAmount2 := aliceAmount - btcutil.Amount(6100)
|
||||||
htlc, preimage = createHTLC(0, htlcAmount2)
|
htlc, preimage = createHTLC(0, htlcAmount2)
|
||||||
if _, err := aliceChannel.AddHTLC(htlc); err != nil {
|
if _, err := aliceChannel.AddHTLC(htlc); err != nil {
|
||||||
t.Fatalf("alice unable to add htlc: %v", err)
|
t.Fatalf("alice unable to add htlc: %v", err)
|
||||||
@ -1622,7 +1626,7 @@ func TestCooperativeCloseDustAdherence(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if closeTx.TxOut[0].Value != int64(aliceBal-calcStaticFee(0)) {
|
if closeTx.TxOut[0].Value != int64(aliceBal-calcStaticFee(0)) {
|
||||||
t.Fatalf("alice's balance is incorrect: expected %v, got %v",
|
t.Fatalf("alice's balance is incorrect: expected %v, got %v",
|
||||||
aliceBal-calcStaticFee(0), closeTx.TxOut[0].Value)
|
int64(aliceBal-calcStaticFee(0)), closeTx.TxOut[0].Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, we'll modify the current balances and dust limits such that
|
// Finally, we'll modify the current balances and dust limits such that
|
||||||
|
Loading…
Reference in New Issue
Block a user