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:
Olaoluwa Osuntokun 2017-05-16 19:05:12 -07:00
parent 82f591dbab
commit e689ef61dd
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
2 changed files with 30 additions and 21 deletions

@ -1256,10 +1256,8 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
commitChain = lc.localCommitChain
}
// TODO(roasbeef): don't assume view is always fetched from tip?
var ourBalance, theirBalance btcutil.Amount
ourBalance = commitChain.tip().ourBalance
theirBalance = commitChain.tip().theirBalance
ourBalance := commitChain.tip().ourBalance
theirBalance := commitChain.tip().theirBalance
// Add the fee from the previous commitment state back to the
// initiator's balance, so that the fee can be recalculated and
@ -1307,20 +1305,28 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
numHTLCs++
}
// Calculate the fee for the commitment transaction based on its size.
commitFee := btcutil.Amount(lc.feeEstimator.EstimateFeePerWeight(1)) *
(commitWeight + btcutil.Amount(htlcWeight*numHTLCs)) / 1000
// Next, we'll calculate the fee for the commitment transaction based
// on its total weight. Once we have the total weight, we'll multiply
// 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 {
ourBalance = ourBalance - commitFee
} else if !lc.channelState.IsInitiator {
theirBalance = theirBalance - commitFee
}
var selfKey *btcec.PublicKey
var remoteKey *btcec.PublicKey
var delay uint32
var delayBalance, p2wkhBalance btcutil.Amount
var (
selfKey *btcec.PublicKey
remoteKey *btcec.PublicKey
delay uint32
delayBalance, p2wkhBalance btcutil.Amount
)
if remoteChain {
selfKey = lc.channelState.TheirCommitKey
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.
// For a cooperative close, there should be no HTLCs.
commitFee := btcutil.Amount(lc.feeEstimator.EstimateFeePerWeight(1)) *
commitWeight / 1000
commitFee := (lc.channelState.FeePerKw * commitWeight) / 1000
if lc.channelState.IsInitiator {
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.
// For a cooperative close, there should be no HTLCs.
commitFee := btcutil.Amount(lc.feeEstimator.EstimateFeePerWeight(1)) *
commitWeight / 1000
// TODO(roasbeef): should be using fee passed in
commitFee := (lc.channelState.FeePerKw * commitWeight) / 1000
if lc.channelState.IsInitiator {
lc.channelState.OurBalance = lc.channelState.OurBalance - commitFee

@ -186,7 +186,7 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
channelCapacity := btcutil.Amount(10 * 1e8)
channelBal := channelCapacity / 2
aliceDustLimit := btcutil.Amount(200)
bobDustLimit := btcutil.Amount(800)
bobDustLimit := btcutil.Amount(1300)
csvTimeoutAlice := uint32(5)
csvTimeoutBob := uint32(4)
@ -244,10 +244,12 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
var obsfucator [StateHintSize]byte
copy(obsfucator[:], aliceFirstRevoke[:])
feePerKw := btcutil.Amount(6000)
aliceChannelState := &channeldb.OpenChannel{
IdentityPub: aliceKeyPub,
ChanID: prevOut,
ChanType: channeldb.SingleFunder,
FeePerKw: feePerKw,
IsInitiator: true,
StateHintObsfucator: obsfucator,
OurCommitKey: aliceKeyPub,
@ -272,6 +274,7 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
}
bobChannelState := &channeldb.OpenChannel{
IdentityPub: bobKeyPub,
FeePerKw: feePerKw,
ChanID: prevOut,
ChanType: channeldb.SingleFunder,
IsInitiator: false,
@ -306,7 +309,7 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
bobSigner := &mockSigner{bobKeyPriv}
notifier := &mockNotfier{}
estimator := &StaticFeeEstimator{50, 6}
estimator := &StaticFeeEstimator{24, 6}
channelAlice, err := NewLightningChannel(aliceSigner, notifier,
estimator, aliceChannelState)
@ -614,7 +617,7 @@ func TestCheckCommitTxSize(t *testing.T) {
}
actualCost := blockchain.GetTransactionWeight(btcutil.NewTx(commitTx))
estimatedCost := estimateCommitTxCost(count, false)
estimatedCost := estimateCommitTxWeight(count, false)
diff := int(estimatedCost - actualCost)
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
// only leave a small enough amount to Alice such that Bob will
// 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)
htlcAmount2 := aliceAmount - btcutil.Amount(1000)
htlcAmount2 := aliceAmount - btcutil.Amount(6100)
htlc, preimage = createHTLC(0, htlcAmount2)
if _, err := aliceChannel.AddHTLC(htlc); err != nil {
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)) {
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